1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Binding shader access tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktBindingShaderAccessTests.hpp"
25 
26 #include "vktTestCase.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40 
41 #include "tcuVector.hpp"
42 #include "tcuVectorUtil.hpp"
43 #include "tcuTexture.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuResultCollector.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuRGBA.hpp"
48 #include "tcuSurface.hpp"
49 #include "tcuImageCompare.hpp"
50 
51 #include "deUniquePtr.hpp"
52 #include "deSharedPtr.hpp"
53 #include "deStringUtil.hpp"
54 #include "deArrayUtil.hpp"
55 
56 #include "qpInfo.h"
57 #include <iostream>
58 
59 namespace vkt
60 {
61 namespace BindingModel
62 {
63 namespace
64 {
65 
66 enum ResourceFlag
67 {
68     RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
69 
70     RESOURCE_FLAG_LAST = (1u << 1u)
71 };
72 
73 enum DescriptorUpdateMethod
74 {
75     DESCRIPTOR_UPDATE_METHOD_NORMAL = 0,         //!< use vkUpdateDescriptorSets
76     DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE,      //!< use descriptor update templates
77     DESCRIPTOR_UPDATE_METHOD_WITH_PUSH,          //!< use push descriptor updates
78     DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, //!< use push descriptor update templates
79 
80     DESCRIPTOR_UPDATE_METHOD_LAST
81 };
82 
stringifyDescriptorUpdateMethod(DescriptorUpdateMethod method)83 std::string stringifyDescriptorUpdateMethod(DescriptorUpdateMethod method)
84 {
85     switch (method)
86     {
87     case DESCRIPTOR_UPDATE_METHOD_NORMAL:
88         return "";
89 
90     case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE:
91         return "with_template";
92 
93     case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH:
94         return "with_push";
95 
96     case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE:
97         return "with_push_template";
98 
99     default:
100         return "N/A";
101     }
102 }
103 
104 static const char *const s_quadrantGenVertexPosSource =
105     "    highp int quadPhase = gl_VertexIndex % 6;\n"
106     "    highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
107     "    highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
108     "    highp int quadOriginX = (gl_VertexIndex / 6) % 2;\n"
109     "    highp int quadOriginY = (gl_VertexIndex / 6) / 2;\n"
110     "    quadrant_id = gl_VertexIndex / 6;\n"
111     "    result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
112 
genPerVertexBlock(const vk::VkShaderStageFlagBits stage,const glu::GLSLVersion version)113 std::string genPerVertexBlock(const vk::VkShaderStageFlagBits stage, const glu::GLSLVersion version)
114 {
115     static const char *const block =
116         "gl_PerVertex {\n"
117         "    vec4  gl_Position;\n"
118         "    float gl_PointSize;\n" // not used, but for compatibility with how implicit block is declared in ES
119         "}";
120     std::ostringstream str;
121 
122     if (!glu::glslVersionIsES(version))
123         switch (stage)
124         {
125         case vk::VK_SHADER_STAGE_VERTEX_BIT:
126             str << "out " << block << ";\n";
127             break;
128 
129         case vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
130             str << "in " << block << " gl_in[gl_MaxPatchVertices];\n"
131                 << "out " << block << " gl_out[];\n";
132             break;
133 
134         case vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
135             str << "in " << block << " gl_in[gl_MaxPatchVertices];\n"
136                 << "out " << block << ";\n";
137             break;
138 
139         case vk::VK_SHADER_STAGE_GEOMETRY_BIT:
140             str << "in " << block << " gl_in[];\n"
141                 << "out " << block << ";\n";
142             break;
143 
144         default:
145             break;
146         }
147 
148     return str.str();
149 }
150 
isUniformDescriptorType(vk::VkDescriptorType type)151 bool isUniformDescriptorType(vk::VkDescriptorType type)
152 {
153     return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
154            type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
155 }
156 
isDynamicDescriptorType(vk::VkDescriptorType type)157 bool isDynamicDescriptorType(vk::VkDescriptorType type)
158 {
159     return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
160            type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
161 }
162 
verifyDriverSupport(const uint32_t apiVersion,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const std::vector<std::string> & deviceExtensions,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descType,vk::VkShaderStageFlags activeStages,vk::VkImageViewType viewType=vk::VK_IMAGE_VIEW_TYPE_2D)163 void verifyDriverSupport(const uint32_t apiVersion, const vk::VkPhysicalDeviceFeatures &deviceFeatures,
164                          const std::vector<std::string> &deviceExtensions, DescriptorUpdateMethod updateMethod,
165                          vk::VkDescriptorType descType, vk::VkShaderStageFlags activeStages,
166                          vk::VkImageViewType viewType = vk::VK_IMAGE_VIEW_TYPE_2D)
167 {
168     std::vector<std::string> extensionNames;
169     size_t numExtensionsNeeded = 0;
170 
171     switch (updateMethod)
172     {
173     case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH:
174         extensionNames.push_back("VK_KHR_push_descriptor");
175         break;
176 
177     case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE:
178         extensionNames.push_back("VK_KHR_push_descriptor");
179     // Fallthrough
180     case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE:
181         if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_descriptor_update_template"))
182             extensionNames.push_back("VK_KHR_descriptor_update_template");
183         break;
184 
185     case DESCRIPTOR_UPDATE_METHOD_NORMAL:
186         // no extensions needed
187         break;
188 
189     default:
190         DE_FATAL("Impossible");
191     }
192 
193     numExtensionsNeeded = extensionNames.size();
194 
195     if (numExtensionsNeeded > 0)
196     {
197         for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++)
198         {
199             for (size_t requiredExtNdx = 0; requiredExtNdx < extensionNames.size(); requiredExtNdx++)
200             {
201                 if (deStringEqual(deviceExtensions[deviceExtNdx].c_str(), extensionNames[requiredExtNdx].c_str()))
202                 {
203                     --numExtensionsNeeded;
204                     break;
205                 }
206             }
207 
208             if (numExtensionsNeeded == 0)
209                 break;
210         }
211 
212         if (numExtensionsNeeded > 0)
213         {
214             TCU_THROW(NotSupportedError,
215                       (stringifyDescriptorUpdateMethod(updateMethod) + " tests are not supported").c_str());
216         }
217     }
218 
219     switch (descType)
220     {
221     case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
222     case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
223     case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
224     case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
225     case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
226     case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
227         // These are supported in all stages
228         break;
229 
230     case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
231     case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
232     case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
233     case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
234         if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
235                             vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT))
236         {
237             if (!deviceFeatures.vertexPipelineStoresAndAtomics)
238                 TCU_THROW(NotSupportedError,
239                           (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
240         }
241 
242         if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
243         {
244             if (!deviceFeatures.fragmentStoresAndAtomics)
245                 TCU_THROW(NotSupportedError,
246                           (de::toString(descType) + " is not supported in fragment shaders").c_str());
247         }
248         break;
249 
250     default:
251         DE_FATAL("Impossible");
252     }
253 
254     if (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !deviceFeatures.imageCubeArray)
255         TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
256 }
257 
viewTypeToImageType(vk::VkImageViewType type)258 vk::VkImageType viewTypeToImageType(vk::VkImageViewType type)
259 {
260     switch (type)
261     {
262     case vk::VK_IMAGE_VIEW_TYPE_1D:
263     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
264         return vk::VK_IMAGE_TYPE_1D;
265     case vk::VK_IMAGE_VIEW_TYPE_2D:
266     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
267         return vk::VK_IMAGE_TYPE_2D;
268     case vk::VK_IMAGE_VIEW_TYPE_3D:
269         return vk::VK_IMAGE_TYPE_3D;
270     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
271     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
272         return vk::VK_IMAGE_TYPE_2D;
273 
274     default:
275         DE_FATAL("Impossible");
276         return (vk::VkImageType)0;
277     }
278 }
279 
getImageLayoutForDescriptorType(vk::VkDescriptorType descType)280 vk::VkImageLayout getImageLayoutForDescriptorType(vk::VkDescriptorType descType)
281 {
282     if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
283         return vk::VK_IMAGE_LAYOUT_GENERAL;
284     else
285         return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
286 }
287 
getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid & srcImage)288 uint32_t getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid &srcImage)
289 {
290     uint32_t dataSize = 0;
291     for (int level = 0; level < srcImage.getNumLevels(); ++level)
292     {
293         const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
294 
295         // tightly packed
296         DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
297 
298         dataSize +=
299             srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
300     }
301     return dataSize;
302 }
303 
writeTextureLevelPyramidData(void * dst,uint32_t dstLen,const tcu::TextureLevelPyramid & srcImage,vk::VkImageViewType viewType,std::vector<vk::VkBufferImageCopy> * copySlices)304 void writeTextureLevelPyramidData(void *dst, uint32_t dstLen, const tcu::TextureLevelPyramid &srcImage,
305                                   vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy> *copySlices)
306 {
307     // \note cube is copied face-by-face
308     const uint32_t arraySize =
309         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
310             (srcImage.getLevel(0).getHeight()) :
311         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
312             (srcImage.getLevel(0).getDepth()) :
313         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
314         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
315                                                   (srcImage.getLevel(0).getDepth()) :
316                                                   ((uint32_t)0);
317     uint32_t levelOffset = 0;
318 
319     DE_ASSERT(arraySize != 0);
320 
321     for (int level = 0; level < srcImage.getNumLevels(); ++level)
322     {
323         const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
324         const tcu::PixelBufferAccess dstAccess(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(),
325                                                (uint8_t *)dst + levelOffset);
326         const uint32_t dataSize =
327             srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
328         const uint32_t sliceDataSize = dataSize / arraySize;
329         const int32_t sliceHeight =
330             (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
331                 (1) :
332                 (srcAccess.getHeight());
333         const int32_t sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
334         const tcu::IVec3 sliceSize(srcAccess.getWidth(), sliceHeight, sliceDepth);
335 
336         // tightly packed
337         DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
338 
339         for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
340         {
341             const vk::VkBufferImageCopy copySlice = {
342                 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset
343                 (uint32_t)sliceSize.x(),                                  // bufferRowLength
344                 (uint32_t)sliceSize.y(),                                  // bufferImageHeight
345                 {
346                     vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
347                     (uint32_t)level,               // mipLevel
348                     (uint32_t)sliceNdx,            // arrayLayer
349                     1u,                            // arraySize
350                 },                                 // imageSubresource
351                 {
352                     0,
353                     0,
354                     0,
355                 }, // imageOffset
356                 {
357                     (uint32_t)sliceSize.x(),
358                     (uint32_t)sliceSize.y(),
359                     (uint32_t)sliceSize.z(),
360                 } // imageExtent
361             };
362             copySlices->push_back(copySlice);
363         }
364 
365         DE_ASSERT(arraySize * sliceDataSize == dataSize);
366 
367         tcu::copy(dstAccess, srcAccess);
368         levelOffset += dataSize;
369     }
370 
371     DE_ASSERT(dstLen == levelOffset);
372     DE_UNREF(dstLen);
373 }
374 
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkBuffer buffer,vk::MemoryRequirement requirement)375 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
376                                                         vk::Allocator &allocator, vk::VkBuffer buffer,
377                                                         vk::MemoryRequirement requirement)
378 {
379     const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer);
380     de::MovePtr<vk::Allocation> allocation      = allocator.allocate(requirements, requirement);
381 
382     VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
383     return allocation;
384 }
385 
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkImage image,vk::MemoryRequirement requirement)386 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
387                                                         vk::Allocator &allocator, vk::VkImage image,
388                                                         vk::MemoryRequirement requirement)
389 {
390     const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image);
391     de::MovePtr<vk::Allocation> allocation      = allocator.allocate(requirements, requirement);
392 
393     VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
394     return allocation;
395 }
396 
makeDescriptorImageInfo(vk::VkSampler sampler)397 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkSampler sampler)
398 {
399     return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0);
400 }
401 
makeDescriptorImageInfo(vk::VkImageView imageView,vk::VkImageLayout layout)402 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkImageView imageView, vk::VkImageLayout layout)
403 {
404     return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout);
405 }
406 
drawQuadrantReferenceResult(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & c1,const tcu::Vec4 & c2,const tcu::Vec4 & c3,const tcu::Vec4 & c4)407 void drawQuadrantReferenceResult(const tcu::PixelBufferAccess &dst, const tcu::Vec4 &c1, const tcu::Vec4 &c2,
408                                  const tcu::Vec4 &c3, const tcu::Vec4 &c4)
409 {
410     tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1);
411     tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2),
412                c2);
413     tcu::clear(
414         tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3);
415     tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2,
416                                  dst.getHeight() - dst.getHeight() / 2),
417                c4);
418 }
419 
420 #ifndef CTS_USES_VULKANSC
createTemplateBinding(uint32_t binding,uint32_t arrayElement,uint32_t descriptorCount,vk::VkDescriptorType descriptorType,size_t offset,size_t stride)421 static const vk::VkDescriptorUpdateTemplateEntry createTemplateBinding(uint32_t binding, uint32_t arrayElement,
422                                                                        uint32_t descriptorCount,
423                                                                        vk::VkDescriptorType descriptorType,
424                                                                        size_t offset, size_t stride)
425 {
426     const vk::VkDescriptorUpdateTemplateEntry updateBinding = {binding,        arrayElement, descriptorCount,
427                                                                descriptorType, offset,       stride};
428 
429     return updateBinding;
430 }
431 
432 class RawUpdateRegistry
433 {
434 public:
435     RawUpdateRegistry(void);
436 
437     template <typename Type>
438     void addWriteObject(const Type &updateObject);
439     size_t getWriteObjectOffset(const uint32_t objectId);
440     const uint8_t *getRawPointer() const;
441 
442 private:
443     std::vector<uint8_t> m_updateEntries;
444     std::vector<size_t> m_updateEntryOffsets;
445     size_t m_nextOffset;
446 };
447 
RawUpdateRegistry(void)448 RawUpdateRegistry::RawUpdateRegistry(void) : m_updateEntries(), m_updateEntryOffsets(), m_nextOffset(0)
449 {
450 }
451 
452 template <typename Type>
addWriteObject(const Type & updateObject)453 void RawUpdateRegistry::addWriteObject(const Type &updateObject)
454 {
455     m_updateEntryOffsets.push_back(m_nextOffset);
456 
457     // in this case, elements <=> bytes
458     m_updateEntries.resize(m_nextOffset + sizeof(updateObject));
459     Type *t = reinterpret_cast<Type *>(m_updateEntries.data() + m_nextOffset);
460     *t      = updateObject;
461     m_nextOffset += sizeof(updateObject);
462 }
463 
getWriteObjectOffset(const uint32_t objectId)464 size_t RawUpdateRegistry::getWriteObjectOffset(const uint32_t objectId)
465 {
466     return m_updateEntryOffsets[objectId];
467 }
468 
getRawPointer() const469 const uint8_t *RawUpdateRegistry::getRawPointer() const
470 {
471     return m_updateEntries.data();
472 }
473 #endif
474 
bindDescriptorSets(const vk::DeviceInterface & m_vki,vk::VkCommandBuffer cmdBuffer,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,vk::VkPipelineBindPoint bindPoint,vk::VkPipelineLayout layout,uint32_t first,uint32_t count,const vk::VkDescriptorSet * descriptorSets,uint32_t dynamicOffsetCount,const uint32_t * dynamicOffsets,bool bind2)475 void bindDescriptorSets(const vk::DeviceInterface &m_vki, vk::VkCommandBuffer cmdBuffer,
476                         vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
477                         vk::VkPipelineBindPoint bindPoint, vk::VkPipelineLayout layout, uint32_t first, uint32_t count,
478                         const vk::VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount,
479                         const uint32_t *dynamicOffsets, bool bind2)
480 {
481     DE_UNREF(stageFlags);
482     DE_UNREF(existingStages);
483     if (bind2)
484     {
485 #ifndef CTS_USES_VULKANSC
486         vk::VkBindDescriptorSetsInfoKHR bindDescriptorSetsInfo = {
487             vk::VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR, // VkStructureType sType;
488             DE_NULL,                                             // const void* pNext;
489             existingStages,                                      // VkShaderStageFlags stageFlags;
490             layout,                                              // VkPipelineLayout layout;
491             first,                                               // uint32_t firstSet;
492             count,                                               // uint32_t descriptorSetCount;
493             descriptorSets,                                      // const VkDescriptorSet* pDescriptorSets;
494             dynamicOffsetCount,                                  // uint32_t dynamicOffsetCount;
495             dynamicOffsets                                       // const uint32_t* pDynamicOffsets;
496         };
497         m_vki.cmdBindDescriptorSets2KHR(cmdBuffer, &bindDescriptorSetsInfo);
498 #endif
499     }
500     else
501     {
502         m_vki.cmdBindDescriptorSets(cmdBuffer, bindPoint, layout, first, count, descriptorSets, dynamicOffsetCount,
503                                     dynamicOffsets);
504     }
505 }
506 
507 class SingleTargetRenderInstance : public vkt::TestInstance
508 {
509 public:
510     SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2);
511 
512 private:
513     static vk::Move<vk::VkImage> createColorAttachment(const vk::DeviceInterface &vki, vk::VkDevice device,
514                                                        vk::Allocator &allocator, const tcu::TextureFormat &format,
515                                                        const tcu::UVec2 &size,
516                                                        de::MovePtr<vk::Allocation> *outAllocation);
517 
518     static vk::Move<vk::VkImageView> createColorAttachmentView(const vk::DeviceInterface &vki, vk::VkDevice device,
519                                                                const tcu::TextureFormat &format, vk::VkImage image);
520 
521     static vk::Move<vk::VkFramebuffer> createFramebuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
522                                                          vk::VkRenderPass renderpass,
523                                                          vk::VkImageView colorAttachmentView, const tcu::UVec2 &size);
524 
525     static vk::Move<vk::VkCommandPool> createCommandPool(const vk::DeviceInterface &vki, vk::VkDevice device,
526                                                          uint32_t queueFamilyIndex);
527 
528     virtual void logTestPlan(void) const                                                       = 0;
529     virtual void renderToTarget(void)                                                          = 0;
530     virtual tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const = 0;
531 
532     void readRenderTarget(tcu::TextureLevel &dst);
533     tcu::TestStatus iterate(void);
534 
535 protected:
536     const tcu::TextureFormat m_targetFormat;
537     const tcu::UVec2 m_targetSize;
538     const bool m_bind2;
539 
540     const vk::DeviceInterface &m_vki;
541     const vk::VkDevice m_device;
542     const vk::VkQueue m_queue;
543     const uint32_t m_queueFamilyIndex;
544     vk::Allocator &m_allocator;
545     de::MovePtr<vk::Allocation> m_colorAttachmentMemory;
546     const vk::Unique<vk::VkImage> m_colorAttachmentImage;
547     const vk::Unique<vk::VkImageView> m_colorAttachmentView;
548     const vk::Unique<vk::VkRenderPass> m_renderPass;
549     const vk::Unique<vk::VkFramebuffer> m_framebuffer;
550     const vk::Unique<vk::VkCommandPool> m_cmdPool;
551 
552     bool m_firstIteration;
553 };
554 
SingleTargetRenderInstance(Context & context,const tcu::UVec2 & size,const bool bind2)555 SingleTargetRenderInstance::SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2)
556     : vkt::TestInstance(context)
557     , m_targetFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
558     , m_targetSize(size)
559     , m_bind2(bind2)
560     , m_vki(context.getDeviceInterface())
561     , m_device(context.getDevice())
562     , m_queue(context.getUniversalQueue())
563     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
564     , m_allocator(context.getDefaultAllocator())
565     , m_colorAttachmentMemory(DE_NULL)
566     , m_colorAttachmentImage(
567           createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
568     , m_colorAttachmentView(createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
569     , m_renderPass(makeRenderPass(m_vki, m_device, vk::mapTextureFormat(m_targetFormat)))
570     , m_framebuffer(createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
571     , m_cmdPool(createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
572     , m_firstIteration(true)
573 {
574 }
575 
createColorAttachment(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,const tcu::TextureFormat & format,const tcu::UVec2 & size,de::MovePtr<vk::Allocation> * outAllocation)576 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment(const vk::DeviceInterface &vki,
577                                                                         vk::VkDevice device, vk::Allocator &allocator,
578                                                                         const tcu::TextureFormat &format,
579                                                                         const tcu::UVec2 &size,
580                                                                         de::MovePtr<vk::Allocation> *outAllocation)
581 {
582     const vk::VkImageCreateInfo imageInfo = {
583         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
584         DE_NULL,
585         (vk::VkImageCreateFlags)0,
586         vk::VK_IMAGE_TYPE_2D,                                                          // imageType
587         vk::mapTextureFormat(format),                                                  // format
588         {size.x(), size.y(), 1u},                                                      // extent
589         1,                                                                             // mipLevels
590         1,                                                                             // arraySize
591         vk::VK_SAMPLE_COUNT_1_BIT,                                                     // samples
592         vk::VK_IMAGE_TILING_OPTIMAL,                                                   // tiling
593         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
594         vk::VK_SHARING_MODE_EXCLUSIVE,                                                 // sharingMode
595         0u,                                                                            // queueFamilyCount
596         DE_NULL,                                                                       // pQueueFamilyIndices
597         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                                 // initialLayout
598     };
599 
600     vk::Move<vk::VkImage> image(vk::createImage(vki, device, &imageInfo));
601     de::MovePtr<vk::Allocation> allocation(
602         allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
603 
604     *outAllocation = allocation;
605     return image;
606 }
607 
createColorAttachmentView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format,vk::VkImage image)608 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView(const vk::DeviceInterface &vki,
609                                                                                 vk::VkDevice device,
610                                                                                 const tcu::TextureFormat &format,
611                                                                                 vk::VkImage image)
612 {
613     const vk::VkImageViewCreateInfo createInfo = {
614         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
615         DE_NULL,
616         (vk::VkImageViewCreateFlags)0,
617         image,                        // image
618         vk::VK_IMAGE_VIEW_TYPE_2D,    // viewType
619         vk::mapTextureFormat(format), // format
620         vk::makeComponentMappingRGBA(),
621         {
622             vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
623             0u,                            // baseMipLevel
624             1u,                            // mipLevels
625             0u,                            // baseArrayLayer
626             1u,                            // arraySize
627         },
628     };
629 
630     return vk::createImageView(vki, device, &createInfo);
631 }
632 
createFramebuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkRenderPass renderpass,vk::VkImageView colorAttachmentView,const tcu::UVec2 & size)633 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer(const vk::DeviceInterface &vki,
634                                                                           vk::VkDevice device,
635                                                                           vk::VkRenderPass renderpass,
636                                                                           vk::VkImageView colorAttachmentView,
637                                                                           const tcu::UVec2 &size)
638 {
639     const vk::VkFramebufferCreateInfo framebufferCreateInfo = {
640         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
641         DE_NULL,
642         (vk::VkFramebufferCreateFlags)0,
643         renderpass,           // renderPass
644         1u,                   // attachmentCount
645         &colorAttachmentView, // pAttachments
646         size.x(),             // width
647         size.y(),             // height
648         1,                    // layers
649     };
650 
651     return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
652 }
653 
createCommandPool(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex)654 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool(const vk::DeviceInterface &vki,
655                                                                           vk::VkDevice device,
656                                                                           uint32_t queueFamilyIndex)
657 {
658     return vk::createCommandPool(vki, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
659 }
660 
readRenderTarget(tcu::TextureLevel & dst)661 void SingleTargetRenderInstance::readRenderTarget(tcu::TextureLevel &dst)
662 {
663     const uint64_t pixelDataSize = (uint64_t)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
664     const vk::VkBufferCreateInfo bufferCreateInfo = {
665         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
666         DE_NULL,
667         0u,                                   // flags
668         pixelDataSize,                        // size
669         vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
670         vk::VK_SHARING_MODE_EXCLUSIVE,        // sharingMode
671         0u,                                   // queueFamilyCount
672         DE_NULL,                              // pQueueFamilyIndices
673     };
674     const vk::Unique<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
675 
676     const de::MovePtr<vk::Allocation> bufferMemory =
677         allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
678 
679     const vk::Unique<vk::VkCommandBuffer> cmd(
680         vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
681 
682     // copy content to buffer
683     beginCommandBuffer(m_vki, *cmd);
684     copyImageToBuffer(m_vki, *cmd, *m_colorAttachmentImage, *buffer, tcu::IVec2(m_targetSize.x(), m_targetSize.y()));
685     endCommandBuffer(m_vki, *cmd);
686 
687     submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
688 
689     dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
690 
691     // copy data
692     invalidateAlloc(m_vki, m_device, *bufferMemory);
693     tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
694 }
695 
iterate(void)696 tcu::TestStatus SingleTargetRenderInstance::iterate(void)
697 {
698     tcu::TextureLevel resultImage;
699 
700     // log
701     if (m_firstIteration)
702     {
703         logTestPlan();
704         m_firstIteration = false;
705     }
706 
707     // render
708     {
709         // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
710         const vk::VkImageSubresourceRange fullSubrange = {
711             vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
712             0u,                            // baseMipLevel
713             1u,                            // mipLevels
714             0u,                            // baseArraySlice
715             1u,                            // arraySize
716         };
717         const vk::VkImageMemoryBarrier imageBarrier = {
718             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
719             DE_NULL,
720             0u,                                           // srcAccessMask
721             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // dstAccessMask
722             vk::VK_IMAGE_LAYOUT_UNDEFINED,                // oldLayout
723             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
724             VK_QUEUE_FAMILY_IGNORED,                      // srcQueueFamilyIndex
725             VK_QUEUE_FAMILY_IGNORED,                      // destQueueFamilyIndex
726             *m_colorAttachmentImage,                      // image
727             fullSubrange,                                 // subresourceRange
728         };
729 
730         const vk::Unique<vk::VkCommandBuffer> cmd(
731             vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
732 
733         beginCommandBuffer(m_vki, *cmd);
734         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
735                                  vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0, 0,
736                                  (const vk::VkMemoryBarrier *)DE_NULL, 0, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1,
737                                  &imageBarrier);
738         endCommandBuffer(m_vki, *cmd);
739 
740         submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
741 
742         renderToTarget();
743     }
744 
745     // read and verify
746     readRenderTarget(resultImage);
747 #ifdef CTS_USES_VULKANSC
748     // skip costly verification in main process
749     if (!m_context.getTestContext().getCommandLine().isSubProcess())
750         return tcu::TestStatus::pass("Success");
751 #endif // CTS_USES_VULKANSC
752     return verifyResultImage(resultImage.getAccess());
753 }
754 
755 class RenderInstanceShaders
756 {
757 public:
758     RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
759                           const vk::VkPhysicalDeviceFeatures &deviceFeatures,
760                           const vk::BinaryCollection &programCollection);
761 
hasTessellationStage(void) const762     inline bool hasTessellationStage(void) const
763     {
764         return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0;
765     }
getNumStages(void) const766     inline uint32_t getNumStages(void) const
767     {
768         return (uint32_t)m_stageInfos.size();
769     }
getStages(void) const770     inline const vk::VkPipelineShaderStageCreateInfo *getStages(void) const
771     {
772         return &m_stageInfos[0];
773     }
774 
775 private:
776     void addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
777                   const vk::VkPhysicalDeviceFeatures &deviceFeatures, const vk::BinaryCollection &programCollection,
778                   const char *name, vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule);
779 
780     vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
781                                                                  vk::VkShaderModule shader) const;
782 
783     vk::Move<vk::VkShaderModule> m_vertexShaderModule;
784     vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule;
785     vk::Move<vk::VkShaderModule> m_tessEvalShaderModule;
786     vk::Move<vk::VkShaderModule> m_geometryShaderModule;
787     vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
788     std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos;
789 };
790 
RenderInstanceShaders(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection)791 RenderInstanceShaders::RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
792                                              const vk::VkPhysicalDeviceFeatures &deviceFeatures,
793                                              const vk::BinaryCollection &programCollection)
794 {
795     addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT,
796              &m_vertexShaderModule);
797     addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
798              &m_tessCtrlShaderModule);
799     addStage(vki, device, deviceFeatures, programCollection, "tess_eval",
800              vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule);
801     addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT,
802              &m_geometryShaderModule);
803     addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT,
804              &m_fragmentShaderModule);
805 
806     DE_ASSERT(!m_stageInfos.empty());
807 }
808 
addStage(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection,const char * name,vk::VkShaderStageFlagBits stage,vk::Move<vk::VkShaderModule> * outModule)809 void RenderInstanceShaders::addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
810                                      const vk::VkPhysicalDeviceFeatures &deviceFeatures,
811                                      const vk::BinaryCollection &programCollection, const char *name,
812                                      vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule)
813 {
814     if (programCollection.contains(name))
815     {
816         if (vk::isShaderStageSupported(deviceFeatures, stage))
817         {
818             vk::Move<vk::VkShaderModule> module =
819                 createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
820 
821             m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
822             *outModule = module;
823         }
824         else
825         {
826             // Wait for the GPU to idle so that throwing the exception
827             // below doesn't free in-use GPU resource.
828             vki.deviceWaitIdle(device);
829             TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
830         }
831     }
832 }
833 
getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,vk::VkShaderModule shader) const834 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
835                                                                                     vk::VkShaderModule shader) const
836 {
837     const vk::VkPipelineShaderStageCreateInfo stageCreateInfo = {
838         vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
839         DE_NULL,
840         (vk::VkPipelineShaderStageCreateFlags)0,
841         stage,  // stage
842         shader, // shader
843         "main",
844         DE_NULL, // pSpecializationInfo
845     };
846     return stageCreateInfo;
847 }
848 
849 class SingleCmdRenderInstance : public SingleTargetRenderInstance
850 {
851 public:
852     SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize, const bool bind2);
853 
854 private:
855     vk::Move<vk::VkPipeline> createPipeline(vk::VkPipelineLayout pipelineLayout);
856 
857     virtual vk::VkPipelineLayout getPipelineLayout(void) const     = 0;
858     virtual void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const = 0;
859 
860     void renderToTarget(void);
861 
862     const bool m_isPrimaryCmdBuf;
863 };
864 
SingleCmdRenderInstance(Context & context,bool isPrimaryCmdBuf,const tcu::UVec2 & renderSize,const bool bind2)865 SingleCmdRenderInstance::SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize,
866                                                  const bool bind2)
867     : SingleTargetRenderInstance(context, renderSize, bind2)
868     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
869 {
870 }
871 
createPipeline(vk::VkPipelineLayout pipelineLayout)872 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline(vk::VkPipelineLayout pipelineLayout)
873 {
874     const RenderInstanceShaders shaderStages(m_vki, m_device, m_context.getDeviceFeatures(),
875                                              m_context.getBinaryCollection());
876     const vk::VkPrimitiveTopology topology                          = shaderStages.hasTessellationStage() ?
877                                                                           vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
878                                                                           vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
879     const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
880         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
881         DE_NULL,
882         (vk::VkPipelineVertexInputStateCreateFlags)0,
883         0u,      // bindingCount
884         DE_NULL, // pVertexBindingDescriptions
885         0u,      // attributeCount
886         DE_NULL, // pVertexAttributeDescriptions
887     };
888     const vk::VkPipelineInputAssemblyStateCreateInfo iaState = {
889         vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
890         DE_NULL,
891         (vk::VkPipelineInputAssemblyStateCreateFlags)0,
892         topology, // topology
893         VK_FALSE, // primitiveRestartEnable
894     };
895     const vk::VkPipelineTessellationStateCreateInfo tessState = {
896         vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, DE_NULL,
897         (vk::VkPipelineTessellationStateCreateFlags)0,
898         3u, // patchControlPoints
899     };
900     const vk::VkViewport viewport                       = vk::makeViewport(m_targetSize);
901     const vk::VkRect2D renderArea                       = vk::makeRect2D(m_targetSize);
902     const vk::VkPipelineViewportStateCreateInfo vpState = {
903         vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
904         DE_NULL,
905         (vk::VkPipelineViewportStateCreateFlags)0,
906         1u, // viewportCount
907         &viewport,
908         1u,
909         &renderArea,
910     };
911     const vk::VkPipelineRasterizationStateCreateInfo rsState = {
912         vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
913         DE_NULL,
914         (vk::VkPipelineRasterizationStateCreateFlags)0,
915         VK_FALSE,                            // depthClipEnable
916         VK_FALSE,                            // rasterizerDiscardEnable
917         vk::VK_POLYGON_MODE_FILL,            // fillMode
918         vk::VK_CULL_MODE_NONE,               // cullMode
919         vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
920         VK_FALSE,                            // depthBiasEnable
921         0.0f,                                // depthBias
922         0.0f,                                // depthBiasClamp
923         0.0f,                                // slopeScaledDepthBias
924         1.0f,                                // lineWidth
925     };
926     const vk::VkSampleMask sampleMask                      = 0x01u;
927     const vk::VkPipelineMultisampleStateCreateInfo msState = {
928         vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
929         DE_NULL,
930         (vk::VkPipelineMultisampleStateCreateFlags)0,
931         vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
932         VK_FALSE,                  // sampleShadingEnable
933         0.0f,                      // minSampleShading
934         &sampleMask,               // sampleMask
935         VK_FALSE,                  // alphaToCoverageEnable
936         VK_FALSE,                  // alphaToOneEnable
937     };
938     const vk::VkPipelineDepthStencilStateCreateInfo dsState = {
939         vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
940         DE_NULL,
941         (vk::VkPipelineDepthStencilStateCreateFlags)0,
942         VK_FALSE,                 // depthTestEnable
943         VK_FALSE,                 // depthWriteEnable
944         vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
945         VK_FALSE,                 // depthBoundsTestEnable
946         VK_FALSE,                 // stencilTestEnable
947         {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
948          0u}, // front
949         {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
950          0u},  // back
951         -1.0f, // minDepthBounds
952         +1.0f, // maxDepthBounds
953     };
954     const vk::VkPipelineColorBlendAttachmentState cbAttachment = {
955         VK_FALSE,                 // blendEnable
956         vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor
957         vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
958         vk::VK_BLEND_OP_ADD,      // blendOpColor
959         vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha
960         vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
961         vk::VK_BLEND_OP_ADD,      // blendOpAlpha
962         (vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT | vk::VK_COLOR_COMPONENT_B_BIT |
963          vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask
964     };
965     const vk::VkPipelineColorBlendStateCreateInfo cbState = {
966         vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
967         DE_NULL,
968         (vk::VkPipelineColorBlendStateCreateFlags)0,
969         VK_FALSE,                 // logicOpEnable
970         vk::VK_LOGIC_OP_CLEAR,    // logicOp
971         1u,                       // attachmentCount
972         &cbAttachment,            // pAttachments
973         {0.0f, 0.0f, 0.0f, 0.0f}, // blendConst
974     };
975     const vk::VkGraphicsPipelineCreateInfo createInfo = {
976         vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
977         DE_NULL,
978         (vk::VkPipelineCreateFlags)0,
979         shaderStages.getNumStages(),                                  // stageCount
980         shaderStages.getStages(),                                     // pStages
981         &vertexInputState,                                            // pVertexInputState
982         &iaState,                                                     // pInputAssemblyState
983         (shaderStages.hasTessellationStage() ? &tessState : DE_NULL), // pTessellationState
984         &vpState,                                                     // pViewportState
985         &rsState,                                                     // pRasterState
986         &msState,                                                     // pMultisampleState
987         &dsState,                                                     // pDepthStencilState
988         &cbState,                                                     // pColorBlendState
989         (const vk::VkPipelineDynamicStateCreateInfo *)DE_NULL,        // pDynamicState
990         pipelineLayout,                                               // layout
991         *m_renderPass,                                                // renderPass
992         0u,                                                           // subpass
993         (vk::VkPipeline)0,                                            // basePipelineHandle
994         0u,                                                           // basePipelineIndex
995     };
996     return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
997 }
998 
renderToTarget(void)999 void SingleCmdRenderInstance::renderToTarget(void)
1000 {
1001     const vk::VkRect2D renderArea = {
1002         {0, 0},                               // offset
1003         {m_targetSize.x(), m_targetSize.y()}, // extent
1004     };
1005     const vk::VkCommandBufferInheritanceInfo passCmdBufInheritInfo = {
1006         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1007         DE_NULL,
1008         (vk::VkRenderPass)*m_renderPass,   // renderPass
1009         0u,                                // subpass
1010         (vk::VkFramebuffer)*m_framebuffer, // framebuffer
1011         VK_FALSE,                          // occlusionQueryEnable
1012         (vk::VkQueryControlFlags)0,
1013         (vk::VkQueryPipelineStatisticFlags)0,
1014     };
1015     const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo = {
1016         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1017         DE_NULL,
1018         vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags
1019         &passCmdBufInheritInfo,
1020     };
1021 
1022     const vk::VkPipelineLayout pipelineLayout(getPipelineLayout());
1023     const vk::Unique<vk::VkPipeline> pipeline(createPipeline(pipelineLayout));
1024     const vk::Unique<vk::VkCommandBuffer> mainCmd(
1025         vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1026     const vk::Unique<vk::VkCommandBuffer> passCmd(
1027         (m_isPrimaryCmdBuf) ?
1028             (vk::Move<vk::VkCommandBuffer>()) :
1029             (vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)));
1030     const vk::Unique<vk::VkFence> fence(vk::createFence(m_vki, m_device));
1031     const vk::VkSubpassContents passContents =
1032         (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1033 
1034     if (!m_isPrimaryCmdBuf)
1035     {
1036         VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1037         m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1038         writeDrawCmdBuffer(*passCmd);
1039         endCommandBuffer(m_vki, *passCmd);
1040     }
1041 
1042     beginCommandBuffer(m_vki, *mainCmd);
1043     beginRenderPass(m_vki, *mainCmd, *m_renderPass, *m_framebuffer, renderArea, tcu::Vec4(0.0f), passContents);
1044 
1045     if (m_isPrimaryCmdBuf)
1046     {
1047         m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1048         writeDrawCmdBuffer(*mainCmd);
1049     }
1050     else
1051     {
1052         m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1053     }
1054 
1055     endRenderPass(m_vki, *mainCmd);
1056     endCommandBuffer(m_vki, *mainCmd);
1057 
1058     // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1059     submitCommandsAndWait(m_vki, m_device, m_queue, mainCmd.get());
1060 }
1061 
1062 enum DescriptorSetCount
1063 {
1064     DESCRIPTOR_SET_COUNT_SINGLE = 0,             //!< single descriptor set
1065     DESCRIPTOR_SET_COUNT_MULTIPLE,               //!< multiple descriptor sets
1066     DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS, //!< multiple discontiguous descriptor sets
1067 
1068     DESCRIPTOR_SET_COUNT_LAST
1069 };
1070 
getDescriptorSetCount(DescriptorSetCount count)1071 uint32_t getDescriptorSetCount(DescriptorSetCount count)
1072 {
1073     switch (count)
1074     {
1075     case DESCRIPTOR_SET_COUNT_SINGLE:
1076         return 1u;
1077     case DESCRIPTOR_SET_COUNT_MULTIPLE:
1078     case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1079         return 2u;
1080     default:
1081         DE_FATAL("Impossible");
1082         return 0u;
1083     }
1084 }
1085 
getDescriptorSetNdx(DescriptorSetCount count,uint32_t setNdx)1086 uint32_t getDescriptorSetNdx(DescriptorSetCount count, uint32_t setNdx)
1087 {
1088     DE_ASSERT(setNdx < getDescriptorSetCount(count));
1089 
1090     const uint32_t contiguousNdx[]    = {0, 1};
1091     const uint32_t discontiguousNdx[] = {0, 2};
1092 
1093     switch (count)
1094     {
1095     case DESCRIPTOR_SET_COUNT_SINGLE:
1096         return 0u;
1097     case DESCRIPTOR_SET_COUNT_MULTIPLE:
1098         return contiguousNdx[setNdx];
1099     case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1100         return discontiguousNdx[setNdx];
1101     default:
1102         DE_FATAL("Impossible");
1103         return 0u;
1104     }
1105 }
1106 
1107 enum ShaderInputInterface
1108 {
1109     SHADER_INPUT_SINGLE_DESCRIPTOR = 0,              //!< one descriptor
1110     SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS,    //!< multiple descriptors with contiguous binding id's
1111     SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with discontiguous binding id's
1112     SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS,     //!< multiple descriptors with large gaps between binding id's
1113     SHADER_INPUT_DESCRIPTOR_ARRAY,                   //!< descriptor array
1114 
1115     SHADER_INPUT_LAST
1116 };
1117 
getInterfaceNumResources(ShaderInputInterface shaderInterface)1118 uint32_t getInterfaceNumResources(ShaderInputInterface shaderInterface)
1119 {
1120     switch (shaderInterface)
1121     {
1122     case SHADER_INPUT_SINGLE_DESCRIPTOR:
1123         return 1u;
1124     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1125         return 2u;
1126     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1127         return 2u;
1128     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1129         return 2u;
1130     case SHADER_INPUT_DESCRIPTOR_ARRAY:
1131         return 2u;
1132 
1133     default:
1134         DE_FATAL("Impossible");
1135         return 0u;
1136     }
1137 }
1138 
getArbitraryBindingIndex(uint32_t ndx)1139 uint32_t getArbitraryBindingIndex(uint32_t ndx)
1140 {
1141     DE_ASSERT(ndx < 2);
1142 
1143     // Binding decoration value can be any 32-bit unsigned integer value.
1144     // 0xFFFE is the largest binding value accepted by glslang
1145 
1146     const uint32_t bufferIndices[] = {
1147 #ifndef CTS_USES_VULKANSC
1148         0x7FFEu, 0xFFFEu
1149 #else
1150         // Use smaller values for VulkanSC since these can produce huge static memory allocations
1151         0x1FFu, 0x3FFu
1152 #endif
1153     };
1154 
1155     return bufferIndices[ndx];
1156 }
1157 
1158 typedef de::MovePtr<vk::Allocation> AllocationMp;
1159 typedef de::SharedPtr<vk::Allocation> AllocationSp;
1160 typedef vk::Unique<vk::VkBuffer> BufferHandleUp;
1161 typedef de::SharedPtr<BufferHandleUp> BufferHandleSp;
1162 typedef vk::Unique<vk::VkBufferView> BufferViewHandleUp;
1163 typedef de::SharedPtr<BufferViewHandleUp> BufferViewHandleSp;
1164 typedef vk::Unique<vk::VkSampler> SamplerHandleUp;
1165 typedef de::SharedPtr<SamplerHandleUp> SamplerHandleSp;
1166 typedef vk::Unique<vk::VkImage> ImageHandleUp;
1167 typedef de::SharedPtr<ImageHandleUp> ImageHandleSp;
1168 typedef vk::Unique<vk::VkImageView> ImageViewHandleUp;
1169 typedef de::SharedPtr<ImageViewHandleUp> ImageViewHandleSp;
1170 typedef vk::Unique<vk::VkDescriptorSet> DescriptorSetHandleUp;
1171 typedef de::SharedPtr<DescriptorSetHandleUp> DescriptorSetHandleSp;
1172 typedef vk::Unique<vk::VkDescriptorSetLayout> DescriptorSetLayoutHandleUp;
1173 typedef de::SharedPtr<DescriptorSetLayoutHandleUp> DescriptorSetLayoutHandleSp;
1174 #ifndef CTS_USES_VULKANSC
1175 typedef vk::Unique<vk::VkDescriptorUpdateTemplate> UpdateTemplateHandleUp;
1176 typedef de::SharedPtr<UpdateTemplateHandleUp> UpdateTemplateHandleSp;
1177 #endif
1178 
1179 class BufferRenderInstance : public SingleCmdRenderInstance
1180 {
1181 public:
1182     BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1183                          vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1184                          vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1185                          ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1186                          bool dynamicOffsetNonZero, bool bind2);
1187 
1188     static std::vector<uint32_t> getViewOffsets(DescriptorSetCount descriptorSetCount,
1189                                                 ShaderInputInterface shaderInterface, bool setViewOffset);
1190 
1191     static std::vector<uint32_t> getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1192                                                    ShaderInputInterface shaderInterface, bool dynamicOffsetNonZero);
1193 
1194     static std::vector<BufferHandleSp> createSourceBuffers(
1195         const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator,
1196         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1197         ShaderInputInterface shaderInterface, const std::vector<uint32_t> &viewOffset,
1198         const std::vector<uint32_t> &dynamicOffset, std::vector<AllocationSp> &bufferMemory);
1199 
1200     static vk::Move<vk::VkBuffer> createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1201                                                      vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1202                                                      uint32_t setNdx, uint32_t offset, uint32_t bufferSize,
1203                                                      de::MovePtr<vk::Allocation> *outMemory);
1204 
1205     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
1206                                                                vk::VkDescriptorType descriptorType,
1207                                                                DescriptorSetCount descriptorSetCount,
1208                                                                ShaderInputInterface shaderInterface);
1209 
1210     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
1211         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1212         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1213         DescriptorUpdateMethod updateMethod);
1214 
1215     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
1216         const vk::DeviceInterface &vki, vk::VkDevice device,
1217         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
1218 
1219     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
1220         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1221         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1222         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1223         ShaderInputInterface shaderInterface, const std::vector<BufferHandleSp> &buffers,
1224         const std::vector<uint32_t> &offsets, vk::DescriptorSetUpdateBuilder &updateBuilder,
1225         std::vector<uint32_t> &descriptorsPerSet,
1226 #ifndef CTS_USES_VULKANSC
1227         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1228 #endif
1229         vk::VkPipelineLayout pipelineLayout = DE_NULL);
1230 
1231     static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1232                                    vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1233                                    vk::VkBuffer sourceBufferA, const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1234                                    const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1235                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
1236                                    std::vector<uint32_t> &descriptorsPerSet,
1237                                    DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
1238 
1239 #ifndef CTS_USES_VULKANSC
1240     static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
1241                                                vk::VkDescriptorSetLayout descriptorSetLayout, uint32_t setNdx,
1242                                                vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType,
1243                                                ShaderInputInterface shaderInterface, vk::VkBuffer sourceBufferA,
1244                                                const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1245                                                const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1246                                                std::vector<UpdateTemplateHandleSp> &updateTemplates,
1247                                                std::vector<RawUpdateRegistry> &registry, bool withPush = false,
1248                                                vk::VkPipelineLayout pipelineLayout = 0);
1249 #endif
1250 
1251     void logTestPlan(void) const;
1252     vk::VkPipelineLayout getPipelineLayout(void) const;
1253     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
1254     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
1255 
1256     enum
1257     {
1258         RENDER_SIZE      = 128,
1259         BUFFER_DATA_SIZE = 8 * sizeof(float),
1260         BUFFER_SIZE_A    = 2048, //!< a lot more than required
1261         BUFFER_SIZE_B    = 2560, //!< a lot more than required
1262         BUFFER_SIZE_C    = 2128, //!< a lot more than required
1263         BUFFER_SIZE_D    = 2136, //!< a lot more than required
1264 
1265         STATIC_OFFSET_VALUE_A  = 256,
1266         DYNAMIC_OFFSET_VALUE_A = 512,
1267         STATIC_OFFSET_VALUE_B  = 1024,
1268         DYNAMIC_OFFSET_VALUE_B = 768,
1269         STATIC_OFFSET_VALUE_C  = 512,
1270         DYNAMIC_OFFSET_VALUE_C = 512,
1271         STATIC_OFFSET_VALUE_D  = 768,
1272         DYNAMIC_OFFSET_VALUE_D = 1024,
1273     };
1274 
1275     const DescriptorUpdateMethod m_updateMethod;
1276     const vk::VkDescriptorType m_descriptorType;
1277     const DescriptorSetCount m_descriptorSetCount;
1278     const ShaderInputInterface m_shaderInterface;
1279     const bool m_setViewOffset;
1280     const bool m_setDynamicOffset;
1281     const bool m_dynamicOffsetNonZero;
1282     const vk::VkShaderStageFlags m_stageFlags;
1283     const vk::VkShaderStageFlags m_existingStages;
1284 
1285     const std::vector<uint32_t> m_viewOffset;
1286     const std::vector<uint32_t> m_dynamicOffset;
1287 
1288     std::vector<AllocationSp> m_bufferMemory;
1289     const std::vector<BufferHandleSp> m_sourceBuffer;
1290     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
1291 #ifndef CTS_USES_VULKANSC
1292     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
1293     std::vector<RawUpdateRegistry> m_updateRegistry;
1294 #endif
1295     vk::DescriptorSetUpdateBuilder m_updateBuilder;
1296     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
1297     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
1298     std::vector<uint32_t> m_descriptorsPerSet;
1299     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
1300 };
1301 
BufferRenderInstance(Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero,bool bind2)1302 BufferRenderInstance::BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1303                                            vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1304                                            vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1305                                            ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1306                                            bool dynamicOffsetNonZero, bool bind2)
1307     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
1308     , m_updateMethod(updateMethod)
1309     , m_descriptorType(descriptorType)
1310     , m_descriptorSetCount(descriptorSetCount)
1311     , m_shaderInterface(shaderInterface)
1312     , m_setViewOffset(viewOffset)
1313     , m_setDynamicOffset(dynamicOffset)
1314     , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
1315     , m_stageFlags(stageFlags)
1316     , m_existingStages(existingStages)
1317     , m_viewOffset(getViewOffsets(m_descriptorSetCount, m_shaderInterface, m_setViewOffset))
1318     , m_dynamicOffset(getDynamicOffsets(m_descriptorSetCount, m_shaderInterface, m_dynamicOffsetNonZero))
1319     , m_bufferMemory()
1320     , m_sourceBuffer(createSourceBuffers(m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount,
1321                                          m_shaderInterface, m_viewOffset, m_dynamicOffset, m_bufferMemory))
1322     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
1323 #ifndef CTS_USES_VULKANSC
1324     , m_updateTemplates()
1325     , m_updateRegistry()
1326 #endif
1327     , m_updateBuilder()
1328     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
1329                                                         m_shaderInterface, m_stageFlags, m_updateMethod))
1330     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
1331     , m_descriptorsPerSet()
1332     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorSetLayouts, *m_descriptorPool,
1333                                             m_descriptorType, m_descriptorSetCount, m_shaderInterface, m_sourceBuffer,
1334                                             m_viewOffset, m_updateBuilder, m_descriptorsPerSet,
1335 #ifndef CTS_USES_VULKANSC
1336                                             m_updateTemplates, m_updateRegistry,
1337 #endif
1338                                             *m_pipelineLayout))
1339 {
1340     if (m_setDynamicOffset)
1341         DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1342     if (m_dynamicOffsetNonZero)
1343         DE_ASSERT(m_setDynamicOffset);
1344 }
1345 
getViewOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool setViewOffset)1346 std::vector<uint32_t> BufferRenderInstance::getViewOffsets(DescriptorSetCount descriptorSetCount,
1347                                                            ShaderInputInterface shaderInterface, bool setViewOffset)
1348 {
1349     const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1350     std::vector<uint32_t> viewOffset;
1351 
1352     for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1353     {
1354         const uint32_t staticOffsetValues[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B, STATIC_OFFSET_VALUE_C,
1355                                                STATIC_OFFSET_VALUE_D};
1356 
1357         viewOffset.push_back(
1358             setViewOffset ? (staticOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1359     }
1360 
1361     return viewOffset;
1362 }
1363 
getDynamicOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool dynamicOffsetNonZero)1364 std::vector<uint32_t> BufferRenderInstance::getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1365                                                               ShaderInputInterface shaderInterface,
1366                                                               bool dynamicOffsetNonZero)
1367 {
1368     const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1369     std::vector<uint32_t> dynamicOffset;
1370 
1371     for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1372     {
1373         const uint32_t dynamicOffsetValues[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B, DYNAMIC_OFFSET_VALUE_C,
1374                                                 DYNAMIC_OFFSET_VALUE_D};
1375 
1376         dynamicOffset.push_back(
1377             dynamicOffsetNonZero ? (dynamicOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1378     }
1379 
1380     return dynamicOffset;
1381 }
1382 
createSourceBuffers(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<uint32_t> & viewOffset,const std::vector<uint32_t> & dynamicOffset,std::vector<AllocationSp> & bufferMemory)1383 std::vector<BufferHandleSp> BufferRenderInstance::createSourceBuffers(
1384     const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1385     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1386     const std::vector<uint32_t> &viewOffset, const std::vector<uint32_t> &dynamicOffset,
1387     std::vector<AllocationSp> &bufferMemory)
1388 {
1389     const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1390     std::vector<uint32_t> effectiveOffset;
1391     std::vector<uint32_t> bufferSize;
1392     std::vector<BufferHandleSp> sourceBuffers;
1393 
1394     for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1395     {
1396         const uint32_t bufferSizeValues[] = {BUFFER_SIZE_A, BUFFER_SIZE_B, BUFFER_SIZE_C, BUFFER_SIZE_D};
1397 
1398         effectiveOffset.push_back(isDynamicDescriptorType(descriptorType) ?
1399                                       (viewOffset[bufferNdx] + dynamicOffset[bufferNdx]) :
1400                                       (viewOffset[bufferNdx]));
1401         bufferSize.push_back(bufferSizeValues[bufferNdx % getInterfaceNumResources(shaderInterface)]);
1402     }
1403 
1404     // Create source buffers
1405     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1406     {
1407         for (uint32_t bufferNdx = 0; bufferNdx < getInterfaceNumResources(shaderInterface); bufferNdx++)
1408         {
1409             de::MovePtr<vk::Allocation> memory;
1410             vk::Move<vk::VkBuffer> buffer =
1411                 createSourceBuffer(vki, device, allocator, descriptorType, setNdx, effectiveOffset[bufferNdx],
1412                                    bufferSize[bufferNdx], &memory);
1413 
1414             bufferMemory.push_back(AllocationSp(memory.release()));
1415             sourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
1416         }
1417     }
1418 
1419     return sourceBuffers;
1420 }
1421 
createSourceBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,uint32_t setNdx,uint32_t offset,uint32_t bufferSize,de::MovePtr<vk::Allocation> * outMemory)1422 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1423                                                                 vk::Allocator &allocator,
1424                                                                 vk::VkDescriptorType descriptorType, uint32_t setNdx,
1425                                                                 uint32_t offset, uint32_t bufferSize,
1426                                                                 de::MovePtr<vk::Allocation> *outMemory)
1427 {
1428     static const float s_colors[] = {
1429         0.0f, 1.0f, 0.0f, 1.0f, // green
1430         1.0f, 1.0f, 0.0f, 1.0f, // yellow
1431         0.0f, 0.0f, 1.0f, 1.0f, // blue
1432         1.0f, 0.0f, 0.0f, 1.0f  // red
1433     };
1434     DE_STATIC_ASSERT(sizeof(s_colors) / 2 == BUFFER_DATA_SIZE);
1435     DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1436     DE_ASSERT(offset % sizeof(float) == 0);
1437     DE_ASSERT(bufferSize % sizeof(float) == 0);
1438 
1439     const bool isUniformBuffer = isUniformDescriptorType(descriptorType);
1440     const vk::VkBufferUsageFlags usageFlags =
1441         (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1442     const float preGuardValue                     = 0.5f;
1443     const float postGuardValue                    = 0.75f;
1444     const vk::VkBufferCreateInfo bufferCreateInfo = {
1445         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1446         DE_NULL,
1447         0u,                            // flags
1448         bufferSize,                    // size
1449         usageFlags,                    // usage
1450         vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1451         0u,                            // queueFamilyCount
1452         DE_NULL,                       // pQueueFamilyIndices
1453     };
1454     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &bufferCreateInfo));
1455     de::MovePtr<vk::Allocation> bufferMemory =
1456         allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1457     void *const mapPtr = bufferMemory->getHostPtr();
1458 
1459     // guard with interesting values
1460     for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1461         deMemcpy((uint8_t *)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1462 
1463     deMemcpy((uint8_t *)mapPtr + offset, &s_colors[8 * (setNdx % 2)], sizeof(s_colors) / 2);
1464     for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors) / 2;
1465          postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1466         deMemcpy((uint8_t *)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1467     deMemset((uint8_t *)mapPtr + offset + sizeof(s_colors) / 2, 0x5A,
1468              (size_t)bufferSize - (size_t)offset -
1469                  sizeof(s_colors) / 2); // fill with interesting pattern that produces valid floats
1470 
1471     flushAlloc(vki, device, *bufferMemory);
1472 
1473     // Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
1474 
1475     *outMemory = bufferMemory;
1476     return buffer;
1477 }
1478 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)1479 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
1480                                                                           vk::VkDevice device,
1481                                                                           vk::VkDescriptorType descriptorType,
1482                                                                           DescriptorSetCount descriptorSetCount,
1483                                                                           ShaderInputInterface shaderInterface)
1484 {
1485     return vk::DescriptorPoolBuilder()
1486         .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
1487         .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1488                getDescriptorSetCount(descriptorSetCount));
1489 }
1490 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)1491 std::vector<DescriptorSetLayoutHandleSp> BufferRenderInstance::createDescriptorSetLayouts(
1492     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1493     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1494     DescriptorUpdateMethod updateMethod)
1495 {
1496 #ifdef CTS_USES_VULKANSC
1497     DE_UNREF(updateMethod);
1498 #endif
1499     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
1500 
1501 #ifndef CTS_USES_VULKANSC
1502     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
1503         updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1504     {
1505         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
1506     }
1507 #endif
1508 
1509     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
1510 
1511     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1512     {
1513         vk::DescriptorSetLayoutBuilder builder;
1514         switch (shaderInterface)
1515         {
1516         case SHADER_INPUT_SINGLE_DESCRIPTOR:
1517             builder.addSingleBinding(descriptorType, stageFlags);
1518             break;
1519 
1520         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1521             builder.addSingleBinding(descriptorType, stageFlags);
1522             builder.addSingleBinding(descriptorType, stageFlags);
1523             break;
1524 
1525         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1526             builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
1527             builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
1528             break;
1529 
1530         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1531             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
1532             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
1533             break;
1534 
1535         case SHADER_INPUT_DESCRIPTOR_ARRAY:
1536             builder.addArrayBinding(descriptorType, 2u, stageFlags);
1537             break;
1538 
1539         default:
1540             DE_FATAL("Impossible");
1541         }
1542 
1543         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
1544         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
1545 
1546         // Add an empty descriptor set layout between sets 0 and 2
1547         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
1548         {
1549             vk::DescriptorSetLayoutBuilder emptyBuilder;
1550             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
1551                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
1552             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
1553         }
1554     }
1555     return descriptorSetLayouts;
1556 }
1557 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)1558 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout(
1559     const vk::DeviceInterface &vki, vk::VkDevice device,
1560     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
1561 {
1562     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
1563     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
1564         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
1565 
1566     const vk::VkPipelineLayoutCreateInfo createInfo = {
1567         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1568         DE_NULL,
1569         (vk::VkPipelineLayoutCreateFlags)0,
1570         (uint32_t)layoutHandles.size(), // descriptorSetCount
1571         &layoutHandles.front(),         // pSetLayouts
1572         0u,                             // pushConstantRangeCount
1573         DE_NULL,                        // pPushConstantRanges
1574     };
1575     return vk::createPipelineLayout(vki, device, &createInfo);
1576 }
1577 
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<BufferHandleSp> & buffers,const std::vector<uint32_t> & offsets,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,vk::VkPipelineLayout pipelineLayout)1578 std::vector<DescriptorSetHandleSp> BufferRenderInstance::createDescriptorSets(
1579     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1580     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1581     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1582     const std::vector<BufferHandleSp> &buffers, const std::vector<uint32_t> &offsets,
1583     vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
1584 #ifndef CTS_USES_VULKANSC
1585     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1586 #endif
1587     vk::VkPipelineLayout pipelineLayout)
1588 {
1589 #ifdef CTS_USES_VULKANSC
1590     DE_UNREF(pipelineLayout);
1591 #endif
1592     std::vector<DescriptorSetHandleSp> descriptorSets;
1593 
1594     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1595     {
1596         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
1597         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
1598                                                            descriptorPool, 1u, &layout};
1599 
1600         vk::VkBuffer bufferA = **buffers[(setNdx * getInterfaceNumResources(shaderInterface)) % buffers.size()];
1601         vk::VkBuffer bufferB = **buffers[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % buffers.size()];
1602         uint32_t offsetA     = offsets[(setNdx * getInterfaceNumResources(shaderInterface)) % offsets.size()];
1603         uint32_t offsetB     = offsets[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % offsets.size()];
1604 
1605         vk::Move<vk::VkDescriptorSet> descriptorSet;
1606 
1607         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
1608             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1609         {
1610             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
1611         }
1612         else
1613         {
1614             descriptorSet = vk::Move<vk::VkDescriptorSet>();
1615         }
1616 
1617 #ifndef CTS_USES_VULKANSC
1618         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
1619         {
1620             writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1621                                            bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1622                                            updateRegistry);
1623         }
1624         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1625         {
1626             writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1627                                            bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1628                                            updateRegistry, true, pipelineLayout);
1629         }
1630         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1631         {
1632             writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1633                                *descriptorSet, updateBuilder, descriptorsPerSet, updateMethod);
1634         }
1635         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1636 #endif
1637         {
1638             writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1639                                *descriptorSet, updateBuilder, descriptorsPerSet);
1640         }
1641 
1642         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
1643     }
1644     return descriptorSets;
1645 }
1646 
writeDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkBuffer bufferA,const uint32_t offsetA,vk::VkBuffer bufferB,const uint32_t offsetB,vk::VkDescriptorSet descriptorSet,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)1647 void BufferRenderInstance::writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1648                                               vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1649                                               vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB,
1650                                               const uint32_t offsetB, vk::VkDescriptorSet descriptorSet,
1651                                               vk::DescriptorSetUpdateBuilder &updateBuilder,
1652                                               std::vector<uint32_t> &descriptorsPerSet,
1653                                               DescriptorUpdateMethod updateMethod)
1654 {
1655     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1656         vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1657         vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1658     };
1659     uint32_t numDescriptors = 0u;
1660 
1661     switch (shaderInterface)
1662     {
1663     case SHADER_INPUT_SINGLE_DESCRIPTOR:
1664         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1665                                   &bufferInfos[0]);
1666         numDescriptors++;
1667         break;
1668 
1669     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1670         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1671                                   &bufferInfos[0]);
1672         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
1673                                   &bufferInfos[1]);
1674         numDescriptors += 2;
1675         break;
1676 
1677     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1678         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1679                                   &bufferInfos[0]);
1680         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
1681                                   &bufferInfos[1]);
1682         numDescriptors += 2;
1683         break;
1684 
1685     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1686         updateBuilder.writeSingle(descriptorSet,
1687                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
1688                                   descriptorType, &bufferInfos[0]);
1689         updateBuilder.writeSingle(descriptorSet,
1690                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
1691                                   descriptorType, &bufferInfos[1]);
1692         numDescriptors += 2;
1693         break;
1694 
1695     case SHADER_INPUT_DESCRIPTOR_ARRAY:
1696         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1697                                  2u, bufferInfos);
1698         numDescriptors++;
1699         break;
1700 
1701     default:
1702         DE_FATAL("Impossible");
1703     }
1704 
1705     descriptorsPerSet.push_back(numDescriptors);
1706 
1707     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1708     {
1709         updateBuilder.update(vki, device);
1710         updateBuilder.clear();
1711     }
1712 }
1713 
1714 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkBuffer bufferA,const uint32_t offsetA,vk::VkBuffer bufferB,const uint32_t offsetB,vk::VkDescriptorSet descriptorSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)1715 void BufferRenderInstance::writeDescriptorSetWithTemplate(
1716     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorSetLayout layout, uint32_t setNdx,
1717     vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1718     vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB, const uint32_t offsetB,
1719     vk::VkDescriptorSet descriptorSet, std::vector<UpdateTemplateHandleSp> &updateTemplates,
1720     std::vector<RawUpdateRegistry> &registry, bool withPush, vk::VkPipelineLayout pipelineLayout)
1721 {
1722     DE_UNREF(descriptorPool);
1723     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1724         vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1725         vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1726     };
1727     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
1728     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
1729         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
1730         DE_NULL,
1731         0,
1732         0,       // descriptorUpdateEntryCount
1733         DE_NULL, // pDescriptorUpdateEntries
1734         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
1735                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
1736         layout,
1737         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1738         pipelineLayout,
1739         setNdx};
1740 
1741     RawUpdateRegistry updateRegistry;
1742 
1743     updateRegistry.addWriteObject(bufferInfos[0]);
1744     updateRegistry.addWriteObject(bufferInfos[1]);
1745 
1746     switch (shaderInterface)
1747     {
1748     case SHADER_INPUT_SINGLE_DESCRIPTOR:
1749         updateEntries.push_back(
1750             createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1751         break;
1752 
1753     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1754         updateEntries.push_back(
1755             createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1756         updateEntries.push_back(
1757             createTemplateBinding(1u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1758         break;
1759 
1760     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1761         updateEntries.push_back(
1762             createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1763         updateEntries.push_back(
1764             createTemplateBinding(2u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1765         break;
1766 
1767     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1768         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
1769                                                       updateRegistry.getWriteObjectOffset(0), 0));
1770         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
1771                                                       updateRegistry.getWriteObjectOffset(1), 0));
1772         break;
1773 
1774     case SHADER_INPUT_DESCRIPTOR_ARRAY:
1775         updateEntries.push_back(createTemplateBinding(0u, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
1776                                                       sizeof(bufferInfos[0])));
1777         break;
1778 
1779     default:
1780         DE_FATAL("Impossible");
1781     }
1782 
1783     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
1784     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
1785 
1786     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
1787         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
1788     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
1789     registry.push_back(updateRegistry);
1790 
1791     if (!withPush)
1792     {
1793         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
1794                                             registry.back().getRawPointer());
1795     }
1796 }
1797 #endif
1798 
logTestPlan(void) const1799 void BufferRenderInstance::logTestPlan(void) const
1800 {
1801     std::ostringstream msg;
1802 
1803     msg << "Rendering 2x2 yellow-green grid.\n"
1804         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
1805                                                                     "Multiple descriptor sets. ")
1806         << "Each descriptor set contains "
1807         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
1808             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
1809             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
1810             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
1811             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
1812                                                                                      (const char *)DE_NULL)
1813         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1814         << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1815 
1816     if (isDynamicDescriptorType(m_descriptorType))
1817     {
1818         if (m_setDynamicOffset)
1819         {
1820             msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1821                 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1822         }
1823         else
1824         {
1825             msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1826         }
1827     }
1828 
1829     if (m_stageFlags == 0u)
1830     {
1831         msg << "Descriptors are not accessed in any shader stage.\n";
1832     }
1833     else
1834     {
1835         msg << "Descriptors are accessed in {"
1836             << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
1837             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
1838             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
1839             << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
1840             << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.\n";
1841     }
1842 
1843     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
1844 }
1845 
getPipelineLayout(void) const1846 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout(void) const
1847 {
1848     return *m_pipelineLayout;
1849 }
1850 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const1851 void BufferRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
1852 {
1853     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
1854         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1855     {
1856         std::vector<vk::VkDescriptorSet> sets;
1857         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1858             sets.push_back(**m_descriptorSets[setNdx]);
1859 
1860         switch (m_descriptorSetCount)
1861         {
1862         case DESCRIPTOR_SET_COUNT_SINGLE:
1863         case DESCRIPTOR_SET_COUNT_MULTIPLE:
1864         {
1865             // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1866             const uint32_t numOffsets              = (!m_setDynamicOffset) ? (0u) : ((uint32_t)m_dynamicOffset.size());
1867             const uint32_t *const dynamicOffsetPtr = (!m_setDynamicOffset) ? (DE_NULL) : (&m_dynamicOffset.front());
1868 
1869             bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1870                                getPipelineLayout(), 0, (int)sets.size(), &sets.front(), numOffsets, dynamicOffsetPtr,
1871                                m_bind2);
1872             break;
1873         }
1874         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1875         {
1876             uint32_t dynamicOffsetNdx = 0u;
1877 
1878             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1879             {
1880                 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1881                 const uint32_t numOffsets =
1882                     (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1883                 const uint32_t *const dynamicOffsetPtr =
1884                     (!m_setDynamicOffset) ? (DE_NULL) : (&m_dynamicOffset[dynamicOffsetNdx]);
1885                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
1886 
1887                 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1888                                    getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], numOffsets,
1889                                    dynamicOffsetPtr, m_bind2);
1890 
1891                 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
1892             }
1893             break;
1894         }
1895         default:
1896             DE_FATAL("Impossible");
1897         }
1898     }
1899 #ifndef CTS_USES_VULKANSC
1900     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1901     {
1902         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1903             m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, **m_updateTemplates[setNdx], getPipelineLayout(), setNdx,
1904                                                       (const void *)m_updateRegistry[setNdx].getRawPointer());
1905     }
1906     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1907     {
1908         uint32_t descriptorNdx = 0u;
1909         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1910         {
1911             const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
1912             m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, setNdx,
1913                                            descriptorNdx, numDescriptors);
1914             descriptorNdx += numDescriptors;
1915         }
1916     }
1917 #endif
1918 
1919     m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1920 }
1921 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const1922 tcu::TestStatus BufferRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
1923 {
1924     const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
1925     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
1926     const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
1927     tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
1928 
1929     tcu::Vec4 sample0 = tcu::Vec4(0.0f);
1930     tcu::Vec4 sample1 = tcu::Vec4(0.0f);
1931 
1932     if (m_stageFlags)
1933     {
1934         const tcu::Vec4 colors[] = {
1935             tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
1936             tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
1937             tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
1938             tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
1939         };
1940 
1941         for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
1942         {
1943             sample0 += colors[2 * (setNdx % 2)];
1944             sample1 += colors[2 * (setNdx % 2) + 1];
1945         }
1946 
1947         if (numDescriptorSets > 1)
1948         {
1949             sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
1950             sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
1951         }
1952     }
1953     else
1954     {
1955         sample0 = green;
1956         sample1 = yellow;
1957     }
1958 
1959     drawQuadrantReferenceResult(reference.getAccess(), sample1, sample0, sample0, sample1);
1960 
1961     if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
1962                          result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1963         return tcu::TestStatus::fail("Image verification failed");
1964     else
1965         return tcu::TestStatus::pass("Pass");
1966 }
1967 
1968 class ComputeInstanceResultBuffer
1969 {
1970 public:
1971     enum
1972     {
1973         DATA_SIZE = sizeof(tcu::Vec4[4])
1974     };
1975 
1976     ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator);
1977 
1978     void readResultContentsTo(tcu::Vec4 (*results)[4]) const;
1979 
getBuffer(void) const1980     inline vk::VkBuffer getBuffer(void) const
1981     {
1982         return *m_buffer;
1983     }
getResultReadBarrier(void) const1984     inline const vk::VkBufferMemoryBarrier *getResultReadBarrier(void) const
1985     {
1986         return &m_bufferBarrier;
1987     }
1988 
1989 private:
1990     static vk::Move<vk::VkBuffer> createResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1991                                                      vk::Allocator &allocator,
1992                                                      de::MovePtr<vk::Allocation> *outAllocation);
1993 
1994     static vk::VkBufferMemoryBarrier createResultBufferBarrier(vk::VkBuffer buffer);
1995 
1996     const vk::DeviceInterface &m_vki;
1997     const vk::VkDevice m_device;
1998 
1999     de::MovePtr<vk::Allocation> m_bufferMem;
2000     const vk::Unique<vk::VkBuffer> m_buffer;
2001     const vk::VkBufferMemoryBarrier m_bufferBarrier;
2002 };
2003 
ComputeInstanceResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator)2004 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
2005                                                          vk::Allocator &allocator)
2006     : m_vki(vki)
2007     , m_device(device)
2008     , m_bufferMem(DE_NULL)
2009     , m_buffer(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
2010     , m_bufferBarrier(createResultBufferBarrier(*m_buffer))
2011 {
2012 }
2013 
readResultContentsTo(tcu::Vec4 (* results)[4]) const2014 void ComputeInstanceResultBuffer::readResultContentsTo(tcu::Vec4 (*results)[4]) const
2015 {
2016     invalidateAlloc(m_vki, m_device, *m_bufferMem);
2017     deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
2018 }
2019 
createResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,de::MovePtr<vk::Allocation> * outAllocation)2020 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer(const vk::DeviceInterface &vki,
2021                                                                        vk::VkDevice device, vk::Allocator &allocator,
2022                                                                        de::MovePtr<vk::Allocation> *outAllocation)
2023 {
2024     const vk::VkBufferCreateInfo createInfo = {
2025         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2026         DE_NULL,
2027         0u,                                     // flags
2028         (vk::VkDeviceSize)DATA_SIZE,            // size
2029         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
2030         vk::VK_SHARING_MODE_EXCLUSIVE,          // sharingMode
2031         0u,                                     // queueFamilyCount
2032         DE_NULL,                                // pQueueFamilyIndices
2033     };
2034     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &createInfo));
2035     de::MovePtr<vk::Allocation> allocation(
2036         allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
2037     const float clearValue = -1.0f;
2038     void *mapPtr           = allocation->getHostPtr();
2039 
2040     for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
2041         deMemcpy(((uint8_t *)mapPtr) + offset, &clearValue, sizeof(float));
2042 
2043     flushAlloc(vki, device, *allocation);
2044 
2045     *outAllocation = allocation;
2046     return buffer;
2047 }
2048 
createResultBufferBarrier(vk::VkBuffer buffer)2049 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier(vk::VkBuffer buffer)
2050 {
2051     const vk::VkBufferMemoryBarrier bufferBarrier = {
2052         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2053         DE_NULL,
2054         vk::VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
2055         vk::VK_ACCESS_HOST_READ_BIT,    // dstAccessMask
2056         VK_QUEUE_FAMILY_IGNORED,        // srcQueueFamilyIndex
2057         VK_QUEUE_FAMILY_IGNORED,        // destQueueFamilyIndex
2058         buffer,                         // buffer
2059         (vk::VkDeviceSize)0u,           // offset
2060         DATA_SIZE,                      // size
2061     };
2062     return bufferBarrier;
2063 }
2064 
2065 class ComputePipeline
2066 {
2067 public:
2068     ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device, const vk::BinaryCollection &programCollection,
2069                     uint32_t numDescriptorSets, const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2070 
getPipeline(void) const2071     inline vk::VkPipeline getPipeline(void) const
2072     {
2073         return *m_pipeline;
2074     }
getPipelineLayout(void) const2075     inline vk::VkPipelineLayout getPipelineLayout(void) const
2076     {
2077         return *m_pipelineLayout;
2078     }
2079 
2080 private:
2081     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(const vk::DeviceInterface &vki, vk::VkDevice device,
2082                                                                uint32_t numDescriptorSets,
2083                                                                const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2084 
2085     static vk::Move<vk::VkPipeline> createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2086                                                    const vk::BinaryCollection &programCollection,
2087                                                    vk::VkPipelineLayout layout);
2088 
2089     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
2090     const vk::Unique<vk::VkPipeline> m_pipeline;
2091 };
2092 
ComputePipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2093 ComputePipeline::ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2094                                  const vk::BinaryCollection &programCollection, uint32_t numDescriptorSets,
2095                                  const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2096     : m_pipelineLayout(createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
2097     , m_pipeline(createPipeline(vki, device, programCollection, *m_pipelineLayout))
2098 {
2099 }
2100 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2101 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout(
2102     const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t numDescriptorSets,
2103     const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2104 {
2105     const vk::VkPipelineLayoutCreateInfo createInfo = {
2106         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2107         DE_NULL,
2108         (vk::VkPipelineLayoutCreateFlags)0,
2109         numDescriptorSets,    // descriptorSetCount
2110         descriptorSetLayouts, // pSetLayouts
2111         0u,                   // pushConstantRangeCount
2112         DE_NULL,              // pPushConstantRanges
2113     };
2114     return vk::createPipelineLayout(vki, device, &createInfo);
2115 }
2116 
createPipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,vk::VkPipelineLayout layout)2117 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2118                                                          const vk::BinaryCollection &programCollection,
2119                                                          vk::VkPipelineLayout layout)
2120 {
2121     const vk::Unique<vk::VkShaderModule> computeModule(
2122         vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
2123     const vk::VkPipelineShaderStageCreateInfo cs = {
2124         vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2125         DE_NULL,
2126         (vk::VkPipelineShaderStageCreateFlags)0,
2127         vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
2128         *computeModule,                  // shader
2129         "main",
2130         DE_NULL, // pSpecializationInfo
2131     };
2132     const vk::VkComputePipelineCreateInfo createInfo = {
2133         vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2134         DE_NULL,
2135         0u,                // flags
2136         cs,                // cs
2137         layout,            // layout
2138         (vk::VkPipeline)0, // basePipelineHandle
2139         0u,                // basePipelineIndex
2140     };
2141     return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
2142 }
2143 
2144 class ComputeCommand
2145 {
2146 public:
2147     ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2148                    vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2149                    ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2150                    const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets, const uint32_t *dynamicOffsets,
2151                    int numPreBarriers, const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2152                    const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2);
2153 
2154     void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2155 #ifndef CTS_USES_VULKANSC
2156                        ,
2157                        std::vector<UpdateTemplateHandleSp> *updateTemplates = DE_NULL,
2158                        std::vector<RawUpdateRegistry> *updateRegistry       = DE_NULL
2159 #endif
2160     ) const;
2161 #ifndef CTS_USES_VULKANSC
2162     void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue, vk::DescriptorSetUpdateBuilder &updateBuilder,
2163                        std::vector<uint32_t> &descriptorsPerSet) const;
2164 #endif
2165 
2166 private:
2167     const bool m_bind2;
2168     const vk::DeviceInterface &m_vki;
2169     const vk::VkDevice m_device;
2170     const vk::VkPipeline m_pipeline;
2171     const vk::VkPipelineLayout m_pipelineLayout;
2172     const tcu::UVec3 m_numWorkGroups;
2173     const ShaderInputInterface m_shaderInterface;
2174     const DescriptorSetCount m_descriptorSetCount;
2175     const vk::VkDescriptorSet *const m_descriptorSets;
2176     const int m_numDynamicOffsets;
2177     const uint32_t *const m_dynamicOffsets;
2178     const int m_numPreBarriers;
2179     const vk::VkBufferMemoryBarrier *const m_preBarriers;
2180     const int m_numPostBarriers;
2181     const vk::VkBufferMemoryBarrier *const m_postBarriers;
2182 };
2183 
ComputeCommand(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkPipeline pipeline,vk::VkPipelineLayout pipelineLayout,const tcu::UVec3 & numWorkGroups,ShaderInputInterface shaderInterface,DescriptorSetCount descriptorSetCount,const vk::VkDescriptorSet * descriptorSets,int numDynamicOffsets,const uint32_t * dynamicOffsets,int numPreBarriers,const vk::VkBufferMemoryBarrier * preBarriers,int numPostBarriers,const vk::VkBufferMemoryBarrier * postBarriers,const bool bind2)2184 ComputeCommand::ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2185                                vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2186                                ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2187                                const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets,
2188                                const uint32_t *dynamicOffsets, int numPreBarriers,
2189                                const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2190                                const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2)
2191     : m_bind2(bind2)
2192     , m_vki(vki)
2193     , m_device(device)
2194     , m_pipeline(pipeline)
2195     , m_pipelineLayout(pipelineLayout)
2196     , m_numWorkGroups(numWorkGroups)
2197     , m_shaderInterface(shaderInterface)
2198     , m_descriptorSetCount(descriptorSetCount)
2199     , m_descriptorSets(descriptorSets)
2200     , m_numDynamicOffsets(numDynamicOffsets)
2201     , m_dynamicOffsets(dynamicOffsets)
2202     , m_numPreBarriers(numPreBarriers)
2203     , m_preBarriers(preBarriers)
2204     , m_numPostBarriers(numPostBarriers)
2205     , m_postBarriers(postBarriers)
2206 {
2207 }
2208 
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,std::vector<UpdateTemplateHandleSp> * updateTemplates,std::vector<RawUpdateRegistry> * updateRegistry) const2209 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2210 #ifndef CTS_USES_VULKANSC
2211                                    ,
2212                                    std::vector<UpdateTemplateHandleSp> *updateTemplates,
2213                                    std::vector<RawUpdateRegistry> *updateRegistry
2214 #endif
2215 ) const
2216 {
2217     const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2218         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, DE_NULL,
2219         vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2220         queueFamilyIndex,                         // queueFamilyIndex
2221     };
2222     const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2223 
2224     const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = {
2225         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
2226         DE_NULL,
2227         *cmdPool,                            // cmdPool
2228         vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
2229         1u,                                  // count
2230     };
2231 
2232     const vk::Unique<vk::VkCommandBuffer> cmd(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
2233 
2234     beginCommandBuffer(m_vki, *cmd);
2235 
2236     m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2237 
2238     // normal update
2239 #ifndef CTS_USES_VULKANSC
2240     if (updateTemplates == DE_NULL)
2241 #endif
2242     {
2243         switch (m_descriptorSetCount)
2244         {
2245         case DESCRIPTOR_SET_COUNT_SINGLE:
2246         case DESCRIPTOR_SET_COUNT_MULTIPLE:
2247         {
2248             bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2249                                vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0,
2250                                getDescriptorSetCount(m_descriptorSetCount), m_descriptorSets, m_numDynamicOffsets,
2251                                m_dynamicOffsets, m_bind2);
2252             break;
2253         }
2254         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
2255         {
2256             uint32_t dynamicOffsetNdx = 0u;
2257 
2258             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2259             {
2260                 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
2261                 const uint32_t numOffsets =
2262                     (!m_numDynamicOffsets) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
2263                 const uint32_t *const dynamicOffsetPtr =
2264                     (!m_numDynamicOffsets) ? (DE_NULL) : (&m_dynamicOffsets[dynamicOffsetNdx]);
2265                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
2266 
2267                 bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2268                                    vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, descriptorSetNdx, 1u,
2269                                    &m_descriptorSets[setNdx], numOffsets, dynamicOffsetPtr, m_bind2);
2270 
2271                 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
2272             }
2273             break;
2274         }
2275         default:
2276             DE_FATAL("Impossible");
2277         }
2278     }
2279 #ifndef CTS_USES_VULKANSC
2280     // update with push template
2281     else
2282     {
2283         for (uint32_t setNdx = 0; setNdx < (uint32_t)(*updateTemplates).size(); setNdx++)
2284             m_vki.cmdPushDescriptorSetWithTemplateKHR(*cmd, **(*updateTemplates)[setNdx], m_pipelineLayout,
2285                                                       getDescriptorSetNdx(m_descriptorSetCount, setNdx),
2286                                                       (const void *)(*updateRegistry)[setNdx].getRawPointer());
2287     }
2288 #endif
2289 
2290     if (m_numPreBarriers)
2291         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2292                                  (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPreBarriers,
2293                                  m_preBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2294 
2295     m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
2296     m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
2297                              (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPostBarriers,
2298                              m_postBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2299     endCommandBuffer(m_vki, *cmd);
2300 
2301     submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2302 }
2303 
2304 #ifndef CTS_USES_VULKANSC
2305 //cmdPushDescriptorSet variant
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet) const2306 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue,
2307                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
2308                                    std::vector<uint32_t> &descriptorsPerSet) const
2309 {
2310     const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2311         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, DE_NULL,
2312         vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2313         queueFamilyIndex,                         // queueFamilyIndex
2314     };
2315     const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2316 
2317     const vk::Unique<vk::VkCommandBuffer> cmd(
2318         vk::allocateCommandBuffer(m_vki, m_device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2319 
2320     beginCommandBuffer(m_vki, *cmd);
2321 
2322     m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2323 
2324     {
2325         uint32_t descriptorNdx = 0u;
2326         for (uint32_t setNdx = 0; setNdx < (uint32_t)descriptorsPerSet.size(); setNdx++)
2327         {
2328             const uint32_t numDescriptors = descriptorsPerSet[setNdx];
2329             updateBuilder.updateWithPush(m_vki, *cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout,
2330                                          getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
2331                                          numDescriptors);
2332             descriptorNdx += numDescriptors;
2333         }
2334     }
2335 
2336     if (m_numPreBarriers)
2337         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2338                                  (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPreBarriers,
2339                                  m_preBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2340 
2341     m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
2342     m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
2343                              (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, m_numPostBarriers,
2344                              m_postBarriers, 0, (const vk::VkImageMemoryBarrier *)DE_NULL);
2345     endCommandBuffer(m_vki, *cmd);
2346 
2347     submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2348 }
2349 #endif
2350 
2351 class BufferComputeInstance : public vkt::TestInstance
2352 {
2353 public:
2354     BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
2355                           DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, bool viewOffset,
2356                           bool dynamicOffset, bool dynamicOffsetNonZero, bool bind2);
2357 
2358 private:
2359     vk::Move<vk::VkBuffer> createColorDataBuffer(uint32_t offset, uint32_t bufferSize, const tcu::Vec4 &value1,
2360                                                  const tcu::Vec4 &value2, de::MovePtr<vk::Allocation> *outAllocation);
2361     vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
2362     vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
2363     vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
2364                                                       uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2365                                                       vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2366     void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2367                             vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2368 #ifndef CTS_USES_VULKANSC
2369     void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
2370                                         uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2371                                         uint32_t offsetB, vk::VkBuffer resBuf, bool withPush = false,
2372                                         vk::VkPipelineLayout pipelineLayout = DE_NULL);
2373 #endif
2374 
2375     tcu::TestStatus iterate(void);
2376     void logTestPlan(void) const;
2377     tcu::TestStatus testResourceAccess(void);
2378 
2379     enum
2380     {
2381         STATIC_OFFSET_VALUE_A  = 256,
2382         DYNAMIC_OFFSET_VALUE_A = 512,
2383         STATIC_OFFSET_VALUE_B  = 1024,
2384         DYNAMIC_OFFSET_VALUE_B = 768,
2385     };
2386 
2387     const DescriptorUpdateMethod m_updateMethod;
2388     const vk::VkDescriptorType m_descriptorType;
2389     const DescriptorSetCount m_descriptorSetCount;
2390     const ShaderInputInterface m_shaderInterface;
2391     const bool m_setViewOffset;
2392     const bool m_setDynamicOffset;
2393     const bool m_dynamicOffsetNonZero;
2394     const bool m_bind2;
2395 
2396 #ifndef CTS_USES_VULKANSC
2397     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
2398 #endif
2399     const vk::DeviceInterface &m_vki;
2400     const vk::VkDevice m_device;
2401     const vk::VkQueue m_queue;
2402     const uint32_t m_queueFamilyIndex;
2403     vk::Allocator &m_allocator;
2404 
2405     const ComputeInstanceResultBuffer m_result;
2406 
2407 #ifndef CTS_USES_VULKANSC
2408     std::vector<RawUpdateRegistry> m_updateRegistry;
2409 #endif
2410     vk::DescriptorSetUpdateBuilder m_updateBuilder;
2411     std::vector<uint32_t> m_descriptorsPerSet;
2412 };
2413 
BufferComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero,bool bind2)2414 BufferComputeInstance::BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
2415                                              vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
2416                                              ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
2417                                              bool dynamicOffsetNonZero, bool bind2)
2418     : vkt::TestInstance(context)
2419     , m_updateMethod(updateMethod)
2420     , m_descriptorType(descriptorType)
2421     , m_descriptorSetCount(descriptorSetCount)
2422     , m_shaderInterface(shaderInterface)
2423     , m_setViewOffset(viewOffset)
2424     , m_setDynamicOffset(dynamicOffset)
2425     , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
2426     , m_bind2(bind2)
2427 #ifndef CTS_USES_VULKANSC
2428     , m_updateTemplates()
2429 #endif
2430     , m_vki(context.getDeviceInterface())
2431     , m_device(context.getDevice())
2432     , m_queue(context.getUniversalQueue())
2433     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
2434     , m_allocator(context.getDefaultAllocator())
2435     , m_result(m_vki, m_device, m_allocator)
2436 #ifndef CTS_USES_VULKANSC
2437     , m_updateRegistry()
2438 #endif
2439     , m_updateBuilder()
2440     , m_descriptorsPerSet()
2441 {
2442     if (m_dynamicOffsetNonZero)
2443         DE_ASSERT(m_setDynamicOffset);
2444 }
2445 
createColorDataBuffer(uint32_t offset,uint32_t bufferSize,const tcu::Vec4 & value1,const tcu::Vec4 & value2,de::MovePtr<vk::Allocation> * outAllocation)2446 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer(uint32_t offset, uint32_t bufferSize,
2447                                                                     const tcu::Vec4 &value1, const tcu::Vec4 &value2,
2448                                                                     de::MovePtr<vk::Allocation> *outAllocation)
2449 {
2450     DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
2451 
2452     const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2453     const vk::VkBufferUsageFlags usageFlags =
2454         (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2455     const vk::VkBufferCreateInfo createInfo = {
2456         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2457         DE_NULL,
2458         0u,                            // flags
2459         (vk::VkDeviceSize)bufferSize,  // size
2460         usageFlags,                    // usage
2461         vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2462         0u,                            // queueFamilyCount
2463         DE_NULL,                       // pQueueFamilyIndices
2464     };
2465     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &createInfo));
2466     de::MovePtr<vk::Allocation> allocation(
2467         allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
2468     void *mapPtr = allocation->getHostPtr();
2469 
2470     if (offset)
2471         deMemset(mapPtr, 0x5A, (size_t)offset);
2472     deMemcpy((uint8_t *)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
2473     deMemcpy((uint8_t *)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
2474     deMemset((uint8_t *)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A,
2475              (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
2476 
2477     flushAlloc(m_vki, m_device, *allocation);
2478 
2479     *outAllocation = allocation;
2480     return buffer;
2481 }
2482 
createDescriptorSetLayout(uint32_t setNdx) const2483 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
2484 {
2485     vk::DescriptorSetLayoutBuilder builder;
2486     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
2487     uint32_t binding                                = 0;
2488 
2489 #ifndef CTS_USES_VULKANSC
2490     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
2491         m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2492     {
2493         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
2494     }
2495 #endif
2496 
2497     if (setNdx == 0)
2498         builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2499                                         binding++);
2500 
2501     switch (m_shaderInterface)
2502     {
2503     case SHADER_INPUT_SINGLE_DESCRIPTOR:
2504         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2505         break;
2506 
2507     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2508         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2509         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2510         break;
2511 
2512     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2513         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 0u);
2514         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2u);
2515         break;
2516 
2517     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2518         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
2519         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
2520         break;
2521 
2522     case SHADER_INPUT_DESCRIPTOR_ARRAY:
2523         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2524         break;
2525 
2526     default:
2527         DE_FATAL("Impossible");
2528     }
2529 
2530     return builder.build(m_vki, m_device, extraFlags);
2531 }
2532 
createDescriptorPool(void) const2533 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool(void) const
2534 {
2535     return vk::DescriptorPoolBuilder()
2536         .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2537         .addType(m_descriptorType,
2538                  getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
2539         .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
2540                getDescriptorSetCount(m_descriptorSetCount));
2541 }
2542 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf)2543 vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
2544                                                                          vk::VkDescriptorSetLayout layout,
2545                                                                          uint32_t setNdx, vk::VkBuffer viewA,
2546                                                                          uint32_t offsetA, vk::VkBuffer viewB,
2547                                                                          uint32_t offsetB, vk::VkBuffer resBuf)
2548 {
2549     const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
2550                                                        pool, 1u, &layout};
2551 
2552     vk::Move<vk::VkDescriptorSet> descriptorSet;
2553     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
2554         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2555     {
2556         descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
2557     }
2558     else
2559     {
2560         descriptorSet = vk::Move<vk::VkDescriptorSet>();
2561     }
2562 
2563 #ifndef CTS_USES_VULKANSC
2564     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
2565     {
2566         writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2567     }
2568     else
2569 #endif
2570         if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2571     {
2572         writeDescriptorSet(*descriptorSet, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2573     }
2574 
2575     return descriptorSet;
2576 }
2577 
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf)2578 void BufferComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA,
2579                                                uint32_t offsetA, vk::VkBuffer viewB, uint32_t offsetB,
2580                                                vk::VkBuffer resBuf)
2581 {
2582     const vk::VkDescriptorBufferInfo resultInfo =
2583         vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2584     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2585         vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2586         vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2587     };
2588 
2589     uint32_t numDescriptors = 0u;
2590     uint32_t binding        = 0u;
2591 
2592     // result
2593     if (setNdx == 0)
2594     {
2595         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2596                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
2597         numDescriptors++;
2598     }
2599 
2600     // buffers
2601     switch (m_shaderInterface)
2602     {
2603     case SHADER_INPUT_SINGLE_DESCRIPTOR:
2604         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2605                                     m_descriptorType, &bufferInfos[0]);
2606         numDescriptors++;
2607         break;
2608 
2609     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2610         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2611                                     m_descriptorType, &bufferInfos[0]);
2612         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2613                                     m_descriptorType, &bufferInfos[1]);
2614         numDescriptors += 2;
2615         break;
2616 
2617     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2618         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
2619                                     m_descriptorType, &bufferInfos[0]);
2620         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
2621                                     m_descriptorType, &bufferInfos[1]);
2622         numDescriptors += 2;
2623         break;
2624 
2625     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2626         m_updateBuilder.writeSingle(descriptorSet,
2627                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
2628                                     m_descriptorType, &bufferInfos[0]);
2629         m_updateBuilder.writeSingle(descriptorSet,
2630                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
2631                                     m_descriptorType, &bufferInfos[1]);
2632         numDescriptors += 2;
2633         break;
2634 
2635     case SHADER_INPUT_DESCRIPTOR_ARRAY:
2636         m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2637                                    m_descriptorType, 2u, bufferInfos);
2638         numDescriptors++;
2639         break;
2640 
2641     default:
2642         DE_FATAL("Impossible");
2643     }
2644 
2645     m_descriptorsPerSet.push_back(numDescriptors);
2646 
2647     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2648     {
2649         m_updateBuilder.update(m_vki, m_device);
2650         m_updateBuilder.clear();
2651     }
2652 }
2653 
2654 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf,bool withPush,vk::VkPipelineLayout pipelineLayout)2655 void BufferComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
2656                                                            vk::VkDescriptorSetLayout layout, uint32_t setNdx,
2657                                                            vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2658                                                            uint32_t offsetB, vk::VkBuffer resBuf, bool withPush,
2659                                                            vk::VkPipelineLayout pipelineLayout)
2660 {
2661     const vk::VkDescriptorBufferInfo resultInfo =
2662         vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2663     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2664         vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2665         vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2666     };
2667     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
2668     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
2669         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
2670         DE_NULL,
2671         0,
2672         0,       // descriptorUpdateEntryCount
2673         DE_NULL, // pDescriptorUpdateEntries
2674         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
2675                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
2676         layout,
2677         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
2678         pipelineLayout,
2679         setNdx};
2680     uint32_t binding = 0u;
2681     uint32_t offset  = 0u;
2682     RawUpdateRegistry updateRegistry;
2683 
2684     if (setNdx == 0)
2685         updateRegistry.addWriteObject(resultInfo);
2686 
2687     updateRegistry.addWriteObject(bufferInfos[0]);
2688     updateRegistry.addWriteObject(bufferInfos[1]);
2689 
2690     // result
2691     if (setNdx == 0)
2692         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2693                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2694 
2695     // buffers
2696     switch (m_shaderInterface)
2697     {
2698     case SHADER_INPUT_SINGLE_DESCRIPTOR:
2699         updateEntries.push_back(
2700             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2701         break;
2702 
2703     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2704         updateEntries.push_back(
2705             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2706         updateEntries.push_back(
2707             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2708         break;
2709 
2710     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2711         updateEntries.push_back(
2712             createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2713         updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
2714                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2715         break;
2716 
2717     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2718         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
2719                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2720         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
2721                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2722         break;
2723 
2724     case SHADER_INPUT_DESCRIPTOR_ARRAY:
2725         updateEntries.push_back(createTemplateBinding(
2726             binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(bufferInfos[0])));
2727         break;
2728 
2729     default:
2730         DE_FATAL("Impossible");
2731     }
2732 
2733     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
2734     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
2735 
2736     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
2737         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
2738     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
2739     m_updateRegistry.push_back(updateRegistry);
2740 
2741     if (!withPush)
2742     {
2743         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
2744                                               m_updateRegistry.back().getRawPointer());
2745     }
2746 }
2747 #endif
2748 
iterate(void)2749 tcu::TestStatus BufferComputeInstance::iterate(void)
2750 {
2751     logTestPlan();
2752     return testResourceAccess();
2753 }
2754 
logTestPlan(void) const2755 void BufferComputeInstance::logTestPlan(void) const
2756 {
2757     std::ostringstream msg;
2758 
2759     msg << "Accessing resource in a compute program.\n"
2760         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
2761                                                                     "Multiple descriptor sets. ")
2762         << "Each descriptor set contains "
2763         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
2764             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
2765             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
2766             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
2767             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
2768                                                                                      (const char *)DE_NULL)
2769         << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2770         << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2771         << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2772 
2773     if (isDynamicDescriptorType(m_descriptorType))
2774     {
2775         if (m_setDynamicOffset)
2776         {
2777             msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2778                 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2779         }
2780         else
2781         {
2782             msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2783         }
2784     }
2785 
2786     msg << "Destination buffer is pre-initialized to -1.\n";
2787 
2788     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2789 }
2790 
testResourceAccess(void)2791 tcu::TestStatus BufferComputeInstance::testResourceAccess(void)
2792 {
2793     enum
2794     {
2795         ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2796     };
2797 
2798     const bool isDynamicCase   = isDynamicDescriptorType(m_descriptorType);
2799     const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2800 
2801     const tcu::Vec4 color[] = {
2802         tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
2803         tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
2804         tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
2805         tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
2806     };
2807 
2808     std::vector<uint32_t> bindTimeOffsets;
2809     std::vector<tcu::Vec4> colors;
2810     std::vector<uint32_t> dataOffsets;
2811     std::vector<uint32_t> viewOffsets;
2812     std::vector<uint32_t> bufferSizes;
2813     std::vector<AllocationSp> bufferMems;
2814     std::vector<BufferHandleSp> buffers;
2815 
2816     for (uint32_t bufferNdx = 0;
2817          bufferNdx < getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2818          bufferNdx++)
2819     {
2820         const uint32_t staticOffsets[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B};
2821 
2822         const uint32_t dynamicOffset[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B};
2823 
2824         const uint32_t parity = bufferNdx % 2;
2825         bindTimeOffsets.push_back((m_dynamicOffsetNonZero) ? (dynamicOffset[parity]) : (0u));
2826 
2827         const uint32_t dataOffset =
2828             ((isDynamicCase) ? (bindTimeOffsets.back()) : 0) + ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2829         const uint32_t viewOffset = ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2830 
2831         colors.push_back(color[bufferNdx % DE_LENGTH_OF_ARRAY(color)]);
2832         dataOffsets.push_back(dataOffset);
2833         viewOffsets.push_back(viewOffset);
2834         bufferSizes.push_back(dataOffsets.back() + ADDRESSABLE_SIZE);
2835 
2836         de::MovePtr<vk::Allocation> bufferMem;
2837         vk::Move<vk::VkBuffer> buffer(createColorDataBuffer(
2838             dataOffsets.back(), bufferSizes.back(), color[(bufferNdx * 2) % DE_LENGTH_OF_ARRAY(color)],
2839             color[(bufferNdx * 2 + 1) % DE_LENGTH_OF_ARRAY(color)], &bufferMem));
2840 
2841         bufferMems.push_back(AllocationSp(bufferMem.release()));
2842         buffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
2843     }
2844 
2845     const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
2846     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
2847     std::vector<DescriptorSetHandleSp> descriptorSets;
2848     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
2849     std::vector<vk::VkDescriptorSet> setHandles;
2850 
2851     const uint32_t numSrcBuffers =
2852         getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2853 
2854     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2855     {
2856         const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2857         const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2858 
2859         vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
2860         vk::Move<vk::VkDescriptorSet> set =
2861             createDescriptorSet(*descriptorPool, *layout, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1],
2862                                 viewOffsets[ndx1], m_result.getBuffer());
2863 
2864         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
2865         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
2866 
2867         layoutHandles.push_back(**descriptorSetLayouts.back());
2868         setHandles.push_back(**descriptorSets.back());
2869 
2870         // Add an empty descriptor set layout between sets 0 and 2
2871         if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
2872         {
2873             vk::DescriptorSetLayoutBuilder emptyBuilder;
2874             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
2875                 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
2876 
2877             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
2878             layoutHandles.push_back(**descriptorSetLayouts.back());
2879         }
2880     }
2881 
2882     const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
2883                                    &layoutHandles.front());
2884     const vk::VkAccessFlags inputBit =
2885         (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
2886 
2887     std::vector<vk::VkBufferMemoryBarrier> bufferBarriers;
2888 
2889     for (uint32_t bufferNdx = 0; bufferNdx < numSrcBuffers; bufferNdx++)
2890     {
2891         const vk::VkBufferMemoryBarrier barrier = {
2892             vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2893             DE_NULL,
2894             vk::VK_ACCESS_HOST_WRITE_BIT,             // srcAccessMask
2895             inputBit,                                 // dstAccessMask
2896             VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex
2897             VK_QUEUE_FAMILY_IGNORED,                  // destQueueFamilyIndex
2898             **buffers[bufferNdx],                     // buffer
2899             (vk::VkDeviceSize)0u,                     // offset
2900             (vk::VkDeviceSize)bufferSizes[bufferNdx], // size
2901         };
2902 
2903         bufferBarriers.push_back(barrier);
2904     }
2905 
2906     const uint32_t *const dynamicOffsets                = (m_setDynamicOffset) ? (&bindTimeOffsets.front()) : (DE_NULL);
2907     const uint32_t numDynamicOffsets                    = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2908     const vk::VkBufferMemoryBarrier *const preBarriers  = &bufferBarriers.front();
2909     const int numPreBarriers                            = numSrcBuffers;
2910     const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
2911     const int numPostBarriers                           = 1;
2912 
2913     const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
2914                                  tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
2915                                  numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
2916                                  postBarriers, m_bind2);
2917 
2918     tcu::Vec4 refQuadrantValue14 = tcu::Vec4(0.0f);
2919     tcu::Vec4 refQuadrantValue23 = tcu::Vec4(0.0f);
2920 
2921     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2922     {
2923         uint32_t offset = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? 1 : 3;
2924         refQuadrantValue14 +=
2925             color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface) + offset) % DE_LENGTH_OF_ARRAY(color)];
2926         refQuadrantValue23 +=
2927             color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface)) % DE_LENGTH_OF_ARRAY(color)];
2928     }
2929 
2930     refQuadrantValue14 = refQuadrantValue14 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2931     refQuadrantValue23 = refQuadrantValue23 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2932 
2933     const tcu::Vec4 references[4] = {
2934         refQuadrantValue14,
2935         refQuadrantValue23,
2936         refQuadrantValue23,
2937         refQuadrantValue14,
2938     };
2939     tcu::Vec4 results[4];
2940 
2941 #ifndef CTS_USES_VULKANSC
2942     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2943     {
2944         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2945         {
2946             const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2947             const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2948 
2949             writeDescriptorSetWithTemplate(DE_NULL, layoutHandles[setNdx], setNdx, **buffers[ndx0], viewOffsets[ndx0],
2950                                            **buffers[ndx1], viewOffsets[ndx1], m_result.getBuffer(), true,
2951                                            pipeline.getPipelineLayout());
2952         }
2953         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
2954     }
2955     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2956     {
2957         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2958         {
2959             const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2960             const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2961 
2962             writeDescriptorSet(DE_NULL, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1], viewOffsets[ndx1],
2963                                m_result.getBuffer());
2964         }
2965 
2966         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
2967     }
2968     else
2969 #endif
2970     {
2971         compute.submitAndWait(m_queueFamilyIndex, m_queue);
2972     }
2973     m_result.readResultContentsTo(&results);
2974 
2975     // verify
2976     if (results[0] == references[0] && results[1] == references[1] && results[2] == references[2] &&
2977         results[3] == references[3])
2978     {
2979         return tcu::TestStatus::pass("Pass");
2980     }
2981     else if (results[0] == tcu::Vec4(-1.0f) && results[1] == tcu::Vec4(-1.0f) && results[2] == tcu::Vec4(-1.0f) &&
2982              results[3] == tcu::Vec4(-1.0f))
2983     {
2984         m_context.getTestContext().getLog()
2985             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
2986         return tcu::TestStatus::fail("Result buffer was not written to");
2987     }
2988     else
2989     {
2990         m_context.getTestContext().getLog()
2991             << tcu::TestLog::Message << "Error expected [" << references[0] << ", " << references[1] << ", "
2992             << references[2] << ", " << references[3] << "], got [" << results[0] << ", " << results[1] << ", "
2993             << results[2] << ", " << results[3] << "]" << tcu::TestLog::EndMessage;
2994         return tcu::TestStatus::fail("Invalid result values");
2995     }
2996 }
2997 
2998 class QuadrantRendederCase : public vkt::TestCase
2999 {
3000 public:
3001     QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
3002                          vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3003                          DescriptorSetCount descriptorSetCount);
3004 
3005 private:
3006     virtual std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const                     = 0;
3007     virtual std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
3008     virtual std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const                      = 0;
3009     virtual std::string genNoAccessSource(void) const                                                       = 0;
3010 
3011     std::string genVertexSource(void) const;
3012     std::string genTessCtrlSource(void) const;
3013     std::string genTessEvalSource(void) const;
3014     std::string genGeometrySource(void) const;
3015     std::string genFragmentSource(void) const;
3016     std::string genComputeSource(void) const;
3017 
3018     void initPrograms(vk::SourceCollections &programCollection) const;
3019 
3020 protected:
3021     const glu::GLSLVersion m_glslVersion;
3022     const vk::VkShaderStageFlags m_exitingStages;
3023     const vk::VkShaderStageFlags m_activeStages;
3024     const DescriptorSetCount m_descriptorSetCount;
3025 };
3026 
QuadrantRendederCase(tcu::TestContext & testCtx,const char * name,glu::GLSLVersion glslVersion,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount)3027 QuadrantRendederCase::QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
3028                                            vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3029                                            DescriptorSetCount descriptorSetCount)
3030     : vkt::TestCase(testCtx, name)
3031     , m_glslVersion(glslVersion)
3032     , m_exitingStages(exitingStages)
3033     , m_activeStages(activeStages)
3034     , m_descriptorSetCount(descriptorSetCount)
3035 {
3036     DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
3037 }
3038 
genVertexSource(void) const3039 std::string QuadrantRendederCase::genVertexSource(void) const
3040 {
3041     const char *const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ?
3042                                           ("tsc") :
3043                                       ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo") :
3044                                       ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag") :
3045                                                                                                      (DE_NULL);
3046     const char *const fragColorPrec =
3047         ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? "highp" : "mediump";
3048     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3049     std::ostringstream buf;
3050 
3051     if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3052     {
3053         const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
3054 
3055         // active vertex shader
3056         buf << versionDecl << "\n" << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT);
3057         buf << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0);
3058         buf << "layout(location = 0) out " << fragColorPrec << " vec4 " << nextStageName << "_color;\n"
3059             << (onlyVS ? "" :
3060                          "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
3061             << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3062             << "{\n"
3063             << "    highp vec4 result_position;\n"
3064             << "    highp int quadrant_id;\n"
3065             << s_quadrantGenVertexPosSource << "    gl_Position = result_position;\n"
3066             << (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n") << "\n"
3067             << "    highp vec4 result_color;\n"
3068             << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT) << "    " << nextStageName
3069             << "_color = result_color;\n"
3070             << "}\n";
3071     }
3072     else
3073     {
3074         // do nothing
3075         buf << versionDecl << "\n"
3076             << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT) << "layout(location = 1) flat out highp int "
3077             << nextStageName << "_quadrant_id;\n"
3078             << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3079             << "{\n"
3080             << "    highp vec4 result_position;\n"
3081             << "    highp int quadrant_id;\n"
3082             << s_quadrantGenVertexPosSource << "    gl_Position = result_position;\n"
3083             << "    " << nextStageName << "_quadrant_id = quadrant_id;\n"
3084             << "}\n";
3085     }
3086 
3087     return buf.str();
3088 }
3089 
genTessCtrlSource(void) const3090 std::string QuadrantRendederCase::genTessCtrlSource(void) const
3091 {
3092     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3093     const bool extRequired        = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3094     const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3095     std::ostringstream buf;
3096 
3097     if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3098     {
3099         // contributing not implemented
3100         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3101 
3102         // active tc shader
3103         buf << versionDecl << "\n"
3104             << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
3105             << "layout(vertices=3) out;\n"
3106             << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
3107             << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3108             << "layout(location = 0) out highp vec4 tes_color[];\n"
3109             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3110             << "{\n"
3111             << "    highp vec4 result_color;\n"
3112             << "    highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
3113             << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) << "\n"
3114             << "    tes_color[gl_InvocationID] = result_color;\n"
3115             << "\n"
3116             << "    // no dynamic input block indexing\n"
3117             << "    highp vec4 position;\n"
3118             << "    if (gl_InvocationID == 0)\n"
3119             << "        position = gl_in[0].gl_Position;\n"
3120             << "    else if (gl_InvocationID == 1)\n"
3121             << "        position = gl_in[1].gl_Position;\n"
3122             << "    else\n"
3123             << "        position = gl_in[2].gl_Position;\n"
3124             << "    gl_out[gl_InvocationID].gl_Position = position;\n"
3125             << "    gl_TessLevelInner[0] = 2.8;\n"
3126             << "    gl_TessLevelInner[1] = 2.8;\n"
3127             << "    gl_TessLevelOuter[0] = 2.8;\n"
3128             << "    gl_TessLevelOuter[1] = 2.8;\n"
3129             << "    gl_TessLevelOuter[2] = 2.8;\n"
3130             << "    gl_TessLevelOuter[3] = 2.8;\n"
3131             << "}\n";
3132     }
3133     else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3134     {
3135         // active te shader, tc passthru
3136         buf << versionDecl << "\n"
3137             << tessExtDecl << "layout(vertices=3) out;\n"
3138             << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3139             << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
3140             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3141             << "{\n"
3142             << "    tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
3143             << "\n"
3144             << "    // no dynamic input block indexing\n"
3145             << "    highp vec4 position;\n"
3146             << "    if (gl_InvocationID == 0)\n"
3147             << "        position = gl_in[0].gl_Position;\n"
3148             << "    else if (gl_InvocationID == 1)\n"
3149             << "        position = gl_in[1].gl_Position;\n"
3150             << "    else\n"
3151             << "        position = gl_in[2].gl_Position;\n"
3152             << "    gl_out[gl_InvocationID].gl_Position = position;\n"
3153             << "    gl_TessLevelInner[0] = 2.8;\n"
3154             << "    gl_TessLevelInner[1] = 2.8;\n"
3155             << "    gl_TessLevelOuter[0] = 2.8;\n"
3156             << "    gl_TessLevelOuter[1] = 2.8;\n"
3157             << "    gl_TessLevelOuter[2] = 2.8;\n"
3158             << "    gl_TessLevelOuter[3] = 2.8;\n"
3159             << "}\n";
3160     }
3161     else
3162     {
3163         // passthrough not implemented
3164         DE_FATAL("not implemented");
3165     }
3166 
3167     return buf.str();
3168 }
3169 
genTessEvalSource(void) const3170 std::string QuadrantRendederCase::genTessEvalSource(void) const
3171 {
3172     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3173     const bool extRequired        = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3174     const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3175     std::ostringstream buf;
3176 
3177     if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3178     {
3179         // contributing not implemented
3180         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
3181 
3182         // active te shader
3183         buf << versionDecl << "\n"
3184             << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3185             << "layout(triangles) in;\n"
3186             << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
3187             << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
3188             << "layout(location = 0) out mediump vec4 frag_color;\n"
3189             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3190             << "{\n"
3191             << "    highp vec4 result_color;\n"
3192             << "    highp int quadrant_id = tes_quadrant_id[0];\n"
3193             << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) << "\n"
3194             << "    frag_color = result_color;\n"
3195             << "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3196                "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3197             << "}\n";
3198     }
3199     else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3200     {
3201         // contributing not implemented
3202         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3203 
3204         // active tc shader, te is passthru
3205         buf << versionDecl << "\n"
3206             << tessExtDecl << "layout(triangles) in;\n"
3207             << "layout(location = 0) in highp vec4 tes_color[];\n"
3208             << "layout(location = 0) out mediump vec4 frag_color;\n"
3209             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3210             << "{\n"
3211             << "    frag_color = tes_color[0];\n"
3212             << "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3213                "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3214             << "}\n";
3215     }
3216     else
3217     {
3218         // passthrough not implemented
3219         DE_FATAL("not implemented");
3220     }
3221 
3222     return buf.str();
3223 }
3224 
genGeometrySource(void) const3225 std::string QuadrantRendederCase::genGeometrySource(void) const
3226 {
3227     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3228     const bool extRequired        = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3229     const char *const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
3230     std::ostringstream buf;
3231 
3232     if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3233     {
3234         // contributing not implemented
3235         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
3236 
3237         // active geometry shader
3238         buf << versionDecl << "\n"
3239             << geomExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "layout(triangles) in;\n"
3240             << "layout(triangle_strip, max_vertices=4) out;\n"
3241             << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
3242             << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
3243             << "layout(location = 0) out mediump vec4 frag_color;\n"
3244             << genPerVertexBlock(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_glslVersion) << "void main (void)\n"
3245             << "{\n"
3246             << "    highp int quadrant_id;\n"
3247             << "    highp vec4 result_color;\n"
3248             << "\n"
3249             << "    quadrant_id = geo_quadrant_id[0];\n"
3250             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3251             << "    gl_Position = gl_in[0].gl_Position;\n"
3252             << "    EmitVertex();\n"
3253             << "\n"
3254             << "    quadrant_id = geo_quadrant_id[1];\n"
3255             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3256             << "    gl_Position = gl_in[1].gl_Position;\n"
3257             << "    EmitVertex();\n"
3258             << "\n"
3259             << "    quadrant_id = geo_quadrant_id[2];\n"
3260             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3261             << "    gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
3262             << "    EmitVertex();\n"
3263             << "\n"
3264             << "    quadrant_id = geo_quadrant_id[0];\n"
3265             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3266             << "    gl_Position = gl_in[2].gl_Position;\n"
3267             << "    EmitVertex();\n"
3268             << "}\n";
3269     }
3270     else
3271     {
3272         // passthrough not implemented
3273         DE_FATAL("not implemented");
3274     }
3275 
3276     return buf.str();
3277 }
3278 
genFragmentSource(void) const3279 std::string QuadrantRendederCase::genFragmentSource(void) const
3280 {
3281     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3282     std::ostringstream buf;
3283 
3284     if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3285     {
3286         buf << versionDecl << "\n"
3287             << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
3288             << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
3289 
3290         if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3291         {
3292             // there are other stages, this is just a contributor
3293             buf << "layout(location = 0) in mediump vec4 frag_color;\n";
3294         }
3295 
3296         buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3297             << "layout(location = 0) out mediump vec4 o_color;\n"
3298             << "void main (void)\n"
3299             << "{\n"
3300             << "    highp int quadrant_id = frag_quadrant_id;\n"
3301             << "    highp vec4 result_color;\n"
3302             << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
3303 
3304         if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3305         {
3306             // just contributor
3307             buf << "    if (frag_quadrant_id < 2)\n"
3308                 << "        o_color = result_color;\n"
3309                 << "    else\n"
3310                 << "        o_color = frag_color;\n";
3311         }
3312         else
3313             buf << "    o_color = result_color;\n";
3314 
3315         buf << "}\n";
3316     }
3317     else if (m_activeStages == 0u)
3318     {
3319         // special case, no active stages
3320         buf << versionDecl << "\n"
3321             << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3322             << "layout(location = 0) out mediump vec4 o_color;\n"
3323             << "void main (void)\n"
3324             << "{\n"
3325             << "    highp int quadrant_id = frag_quadrant_id;\n"
3326             << "    highp vec4 result_color;\n"
3327             << genNoAccessSource() << "    o_color = result_color;\n"
3328             << "}\n";
3329     }
3330     else
3331     {
3332         // passthrough
3333         buf << versionDecl << "\n"
3334             << "layout(location = 0) in mediump vec4 frag_color;\n"
3335                "layout(location = 0) out mediump vec4 o_color;\n"
3336                "void main (void)\n"
3337                "{\n"
3338                "    o_color = frag_color;\n"
3339                "}\n";
3340     }
3341 
3342     return buf.str();
3343 }
3344 
genComputeSource(void) const3345 std::string QuadrantRendederCase::genComputeSource(void) const
3346 {
3347     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3348     std::ostringstream buf;
3349 
3350     buf << versionDecl << "\n"
3351         << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3352         << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3353         << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
3354         << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
3355         << "{\n"
3356         << "    highp vec4 read_colors[4];\n"
3357         << "} b_out;\n"
3358         << "void main (void)\n"
3359         << "{\n"
3360         << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
3361         << "    highp vec4 result_color;\n"
3362         << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3363         << "    b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
3364         << "}\n";
3365 
3366     return buf.str();
3367 }
3368 
initPrograms(vk::SourceCollections & programCollection) const3369 void QuadrantRendederCase::initPrograms(vk::SourceCollections &programCollection) const
3370 {
3371     if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3372         programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
3373 
3374     if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3375         programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
3376 
3377     if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3378         programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
3379 
3380     if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3381         programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
3382 
3383     if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3384         programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
3385 
3386     if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
3387         programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
3388 }
3389 
3390 class BufferDescriptorCase : public QuadrantRendederCase
3391 {
3392 public:
3393     enum
3394     {
3395         FLAG_VIEW_OFFSET            = (1u << 1u),
3396         FLAG_DYNAMIC_OFFSET_ZERO    = (1u << 2u),
3397         FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u),
3398     };
3399     // enum continues where resource flags ends
3400     DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
3401 
3402     BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
3403                          bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3404                          vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3405                          DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags,
3406                          const bool bind2);
3407 
3408 private:
3409     std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
3410     std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
3411     std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
3412     std::string genNoAccessSource(void) const;
3413 
3414     vkt::TestInstance *createInstance(vkt::Context &context) const;
3415 
3416     void checkSupport(Context &context) const;
3417 
3418     const DescriptorUpdateMethod m_updateMethod;
3419     const bool m_viewOffset;
3420     const bool m_dynamicOffsetSet;
3421     const bool m_dynamicOffsetNonZero;
3422     const bool m_isPrimaryCmdBuf;
3423     const vk::VkDescriptorType m_descriptorType;
3424     const DescriptorSetCount m_descriptorSetCount;
3425     const ShaderInputInterface m_shaderInterface;
3426     const bool m_bind2;
3427 };
3428 
BufferDescriptorCase(tcu::TestContext & testCtx,DescriptorUpdateMethod updateMethod,const char * name,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,uint32_t flags,const bool bind2)3429 BufferDescriptorCase::BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod,
3430                                            const char *name, bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3431                                            vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3432                                            DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3433                                            uint32_t flags, const bool bind2)
3434     : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
3435     , m_updateMethod(updateMethod)
3436     , m_viewOffset((flags & FLAG_VIEW_OFFSET) != 0u)
3437     , m_dynamicOffsetSet((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
3438     , m_dynamicOffsetNonZero((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
3439     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
3440     , m_descriptorType(descriptorType)
3441     , m_descriptorSetCount(descriptorSetCount)
3442     , m_shaderInterface(shaderInterface)
3443     , m_bind2(bind2)
3444 {
3445 }
3446 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const3447 std::string BufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
3448 {
3449     DE_UNREF(stage);
3450     return "";
3451 }
3452 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const3453 std::string BufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const
3454 {
3455     DE_UNREF(stage);
3456 
3457     const bool isUniform          = isUniformDescriptorType(m_descriptorType);
3458     const char *const storageType = (isUniform) ? ("uniform") : ("buffer");
3459     const uint32_t numSets        = getDescriptorSetCount(m_descriptorSetCount);
3460 
3461     std::ostringstream buf;
3462 
3463     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3464     {
3465         // Result buffer is bound only to the first descriptor set in compute shader cases
3466         const int descBinding =
3467             numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
3468         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3469         const uint32_t descriptorSet    = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
3470 
3471         switch (m_shaderInterface)
3472         {
3473         case SHADER_INPUT_SINGLE_DESCRIPTOR:
3474             buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3475                 << " BufferName" << setNdxPostfix << "\n"
3476                 << "{\n"
3477                 << "    highp vec4 colorA;\n"
3478                 << "    highp vec4 colorB;\n"
3479                 << "} b_instance" << setNdxPostfix << ";\n";
3480             break;
3481 
3482         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3483             buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3484                 << " BufferName" << setNdxPostfix << "A\n"
3485                 << "{\n"
3486                 << "    highp vec4 colorA;\n"
3487                 << "    highp vec4 colorB;\n"
3488                 << "} b_instance" << setNdxPostfix << "A;\n"
3489                 << "layout(set = " << descriptorSet << ", binding = " << (descBinding + 1) << ", std140) "
3490                 << storageType << " BufferName" << setNdxPostfix << "B\n"
3491                 << "{\n"
3492                 << "    highp vec4 colorA;\n"
3493                 << "    highp vec4 colorB;\n"
3494                 << "} b_instance" << setNdxPostfix << "B;\n";
3495             break;
3496 
3497         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3498             buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding) << ", std140) "
3499                 << storageType << " BufferName" << setNdxPostfix << "A\n"
3500                 << "{\n"
3501                 << "    highp vec4 colorA;\n"
3502                 << "    highp vec4 colorB;\n"
3503                 << "} b_instance" << setNdxPostfix << "A;\n"
3504                 << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding + 2) << ", std140) "
3505                 << storageType << " BufferName" << setNdxPostfix << "B\n"
3506                 << "{\n"
3507                 << "    highp vec4 colorA;\n"
3508                 << "    highp vec4 colorB;\n"
3509                 << "} b_instance" << setNdxPostfix << "B;\n";
3510             break;
3511 
3512         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3513             buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(0))
3514                 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "A\n"
3515                 << "{\n"
3516                 << "    highp vec4 colorA;\n"
3517                 << "    highp vec4 colorB;\n"
3518                 << "} b_instance" << setNdxPostfix << "A;\n"
3519                 << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(1))
3520                 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "B\n"
3521                 << "{\n"
3522                 << "    highp vec4 colorA;\n"
3523                 << "    highp vec4 colorB;\n"
3524                 << "} b_instance" << setNdxPostfix << "B;\n";
3525             break;
3526 
3527         case SHADER_INPUT_DESCRIPTOR_ARRAY:
3528             buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3529                 << " BufferName" << setNdxPostfix << "\n"
3530                 << "{\n"
3531                 << "    highp vec4 colorA;\n"
3532                 << "    highp vec4 colorB;\n"
3533                 << "} b_instances" << setNdxPostfix << "[2];\n";
3534             break;
3535 
3536         default:
3537             DE_FATAL("Impossible");
3538         }
3539     }
3540     return buf.str();
3541 }
3542 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const3543 std::string BufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
3544 {
3545     DE_UNREF(stage);
3546 
3547     const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
3548     std::ostringstream buf;
3549 
3550     buf << "    result_color = vec4(0.0);\n";
3551 
3552     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3553     {
3554         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3555 
3556         switch (m_shaderInterface)
3557         {
3558         case SHADER_INPUT_SINGLE_DESCRIPTOR:
3559             buf << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3560                 << "        result_color += b_instance" << setNdxPostfix << ".colorA;\n"
3561                 << "    else\n"
3562                 << "        result_color += b_instance" << setNdxPostfix << ".colorB;\n";
3563             break;
3564 
3565         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3566         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3567         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3568             buf << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3569                 << "        result_color += b_instance" << setNdxPostfix << "A.colorA;\n"
3570                 << "    else\n"
3571                 << "        result_color += b_instance" << setNdxPostfix << "B.colorB;\n";
3572             break;
3573 
3574         case SHADER_INPUT_DESCRIPTOR_ARRAY:
3575             buf << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3576                 << "        result_color += b_instances" << setNdxPostfix << "[0].colorA;\n"
3577                 << "    else\n"
3578                 << "        result_color += b_instances" << setNdxPostfix << "[1].colorB;\n";
3579             break;
3580 
3581         default:
3582             DE_FATAL("Impossible");
3583         }
3584     }
3585 
3586     if (getDescriptorSetCount(m_descriptorSetCount) > 1)
3587         buf << "    result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
3588 
3589     return buf.str();
3590 }
3591 
genNoAccessSource(void) const3592 std::string BufferDescriptorCase::genNoAccessSource(void) const
3593 {
3594     return "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3595            "        result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
3596            "    else\n"
3597            "        result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
3598 }
3599 
createInstance(vkt::Context & context) const3600 vkt::TestInstance *BufferDescriptorCase::createInstance(vkt::Context &context) const
3601 {
3602     verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
3603                         m_updateMethod, m_descriptorType, m_activeStages);
3604 
3605     if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
3606     {
3607         DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
3608         return new BufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
3609                                          m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero,
3610                                          m_bind2);
3611     }
3612     else
3613         return new BufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
3614                                         m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
3615                                         m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero, m_bind2);
3616 }
3617 
checkSupport(Context & context) const3618 void BufferDescriptorCase::checkSupport(Context &context) const
3619 {
3620     if (m_bind2)
3621         context.requireDeviceFunctionality("VK_KHR_maintenance6");
3622 }
3623 
3624 class ImageInstanceImages
3625 {
3626 public:
3627     ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3628                         vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3629                         vk::VkImageViewType viewType, int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3630                         uint32_t baseArraySlice);
3631 
3632 private:
3633     static std::vector<tcu::TextureLevelPyramid> createSourceImages(int numImages, int numLevels,
3634                                                                     vk::VkImageViewType viewType,
3635                                                                     tcu::TextureFormat imageFormat);
3636 
3637     static std::vector<ImageHandleSp> createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3638                                                    vk::Allocator &allocator, uint32_t queueFamilyIndex,
3639                                                    vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3640                                                    vk::VkImageViewType viewType, std::vector<AllocationSp> &imageMemory,
3641                                                    const std::vector<tcu::TextureLevelPyramid> &sourceImages);
3642 
3643     static std::vector<ImageViewHandleSp> createImageViews(const vk::DeviceInterface &vki, vk::VkDevice device,
3644                                                            vk::VkImageViewType viewType,
3645                                                            const std::vector<tcu::TextureLevelPyramid> &sourceImages,
3646                                                            const std::vector<ImageHandleSp> &images,
3647                                                            uint32_t baseMipLevel, uint32_t baseArraySlice);
3648 
3649     static vk::Move<vk::VkImage> createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3650                                              vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3651                                              vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &sourceImage,
3652                                              de::MovePtr<vk::Allocation> *outAllocation);
3653 
3654     static vk::Move<vk::VkImageView> createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3655                                                      vk::VkImageViewType viewType,
3656                                                      const tcu::TextureLevelPyramid &sourceImage, vk::VkImage image,
3657                                                      uint32_t baseMipLevel, uint32_t baseArraySlice);
3658 
3659     static void populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx);
3660 
3661     static void uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3662                             vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image, vk::VkImageLayout layout,
3663                             vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &data);
3664 
3665 protected:
3666     enum
3667     {
3668         IMAGE_SIZE = 64,
3669         ARRAY_SIZE = 2,
3670     };
3671 
3672     const vk::VkImageViewType m_viewType;
3673     const uint32_t m_baseMipLevel;
3674     const uint32_t m_baseArraySlice;
3675     const tcu::TextureFormat m_imageFormat;
3676     const std::vector<tcu::TextureLevelPyramid> m_sourceImage;
3677     std::vector<AllocationSp> m_imageMemory;
3678     const std::vector<ImageHandleSp> m_image;
3679     const std::vector<ImageViewHandleSp> m_imageView;
3680 };
3681 
ImageInstanceImages(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,vk::VkImageViewType viewType,int numImages,uint32_t numLevels,uint32_t baseMipLevel,uint32_t baseArraySlice)3682 ImageInstanceImages::ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3683                                          vk::VkQueue queue, vk::Allocator &allocator,
3684                                          vk::VkDescriptorType descriptorType, vk::VkImageViewType viewType,
3685                                          int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3686                                          uint32_t baseArraySlice)
3687     : m_viewType(viewType)
3688     , m_baseMipLevel(baseMipLevel)
3689     , m_baseArraySlice(baseArraySlice)
3690     , m_imageFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
3691     , m_sourceImage(createSourceImages(numImages, numLevels, viewType, m_imageFormat))
3692     , m_imageMemory()
3693     , m_image(createImages(vki, device, allocator, queueFamilyIndex, queue, descriptorType, viewType, m_imageMemory,
3694                            m_sourceImage))
3695     , m_imageView(createImageViews(vki, device, viewType, m_sourceImage, m_image, m_baseMipLevel, m_baseArraySlice))
3696 {
3697 }
3698 
createSourceImages(int numImages,int numLevels,vk::VkImageViewType viewType,tcu::TextureFormat imageFormat)3699 std::vector<tcu::TextureLevelPyramid> ImageInstanceImages::createSourceImages(int numImages, int numLevels,
3700                                                                               vk::VkImageViewType viewType,
3701                                                                               tcu::TextureFormat imageFormat)
3702 {
3703     std::vector<tcu::TextureLevelPyramid> sourceImages(numImages, tcu::TextureLevelPyramid(imageFormat, numLevels));
3704 
3705     for (int imageNdx = 0; imageNdx < numImages; imageNdx++)
3706         populateSourceImage(&sourceImages.at(imageNdx), viewType, imageNdx);
3707 
3708     return sourceImages;
3709 }
3710 
createImages(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::VkDescriptorType descriptorType,vk::VkImageViewType viewType,std::vector<AllocationSp> & imageMemory,const std::vector<tcu::TextureLevelPyramid> & sourceImages)3711 std::vector<ImageHandleSp> ImageInstanceImages::createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3712                                                              vk::Allocator &allocator, uint32_t queueFamilyIndex,
3713                                                              vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3714                                                              vk::VkImageViewType viewType,
3715                                                              std::vector<AllocationSp> &imageMemory,
3716                                                              const std::vector<tcu::TextureLevelPyramid> &sourceImages)
3717 {
3718     std::vector<ImageHandleSp> images;
3719     const vk::VkImageLayout layout = getImageLayoutForDescriptorType(descriptorType);
3720 
3721     for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3722     {
3723         de::MovePtr<vk::Allocation> memory;
3724         vk::Move<vk::VkImage> image =
3725             createImage(vki, device, allocator, descriptorType, viewType, sourceImages[imageNdx], &memory);
3726 
3727         uploadImage(vki, device, queueFamilyIndex, queue, allocator, *image, layout, viewType, sourceImages[imageNdx]);
3728 
3729         imageMemory.push_back(AllocationSp(memory.release()));
3730         images.push_back(ImageHandleSp(new ImageHandleUp(image)));
3731     }
3732     return images;
3733 }
3734 
createImageViews(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const std::vector<tcu::TextureLevelPyramid> & sourceImages,const std::vector<ImageHandleSp> & images,uint32_t baseMipLevel,uint32_t baseArraySlice)3735 std::vector<ImageViewHandleSp> ImageInstanceImages::createImageViews(
3736     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkImageViewType viewType,
3737     const std::vector<tcu::TextureLevelPyramid> &sourceImages, const std::vector<ImageHandleSp> &images,
3738     uint32_t baseMipLevel, uint32_t baseArraySlice)
3739 {
3740     std::vector<ImageViewHandleSp> imageViews;
3741     for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3742     {
3743         vk::Move<vk::VkImageView> imageView = createImageView(vki, device, viewType, sourceImages[imageNdx],
3744                                                               **images[imageNdx], baseMipLevel, baseArraySlice);
3745         imageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imageView)));
3746     }
3747     return imageViews;
3748 }
3749 
createImage(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,de::MovePtr<vk::Allocation> * outAllocation)3750 vk::Move<vk::VkImage> ImageInstanceImages::createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3751                                                        vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3752                                                        vk::VkImageViewType viewType,
3753                                                        const tcu::TextureLevelPyramid &sourceImage,
3754                                                        de::MovePtr<vk::Allocation> *outAllocation)
3755 {
3756     const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3757     const bool isCube    = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
3758     const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
3759     const uint32_t readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
3760     const uint32_t arraySize =
3761         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3762             (baseLevel.getHeight()) :
3763         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
3764             (baseLevel.getDepth()) :
3765         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3766         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3767                                                   (baseLevel.getDepth()) // cube: numFaces * numLayers
3768                                                   :
3769                                                   (0);
3770     const vk::VkExtent3D extent = {
3771         // x
3772         (uint32_t)baseLevel.getWidth(),
3773 
3774         // y
3775         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3776             (1u) :
3777             (uint32_t)baseLevel.getHeight(),
3778 
3779         // z
3780         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((uint32_t)baseLevel.getDepth()) : (1u),
3781     };
3782     const vk::VkImageCreateInfo createInfo = {
3783         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3784         DE_NULL,
3785         isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
3786         viewTypeToImageType(viewType),                   // imageType
3787         vk::mapTextureFormat(baseLevel.getFormat()),     // format
3788         extent,                                          // extent
3789         (uint32_t)sourceImage.getNumLevels(),            // mipLevels
3790         arraySize,                                       // arraySize
3791         vk::VK_SAMPLE_COUNT_1_BIT,                       // samples
3792         vk::VK_IMAGE_TILING_OPTIMAL,                     // tiling
3793         readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage
3794         vk::VK_SHARING_MODE_EXCLUSIVE,                   // sharingMode
3795         0u,                                              // queueFamilyCount
3796         DE_NULL,                                         // pQueueFamilyIndices
3797         vk::VK_IMAGE_LAYOUT_UNDEFINED,                   // initialLayout
3798     };
3799     vk::Move<vk::VkImage> image(vk::createImage(vki, device, &createInfo));
3800 
3801     *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
3802     return image;
3803 }
3804 
createImageView(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,vk::VkImage image,uint32_t baseMipLevel,uint32_t baseArraySlice)3805 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3806                                                                vk::VkImageViewType viewType,
3807                                                                const tcu::TextureLevelPyramid &sourceImage,
3808                                                                vk::VkImage image, uint32_t baseMipLevel,
3809                                                                uint32_t baseArraySlice)
3810 {
3811     const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3812     const uint32_t viewTypeBaseSlice =
3813         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3814             (6 * baseArraySlice) :
3815             (baseArraySlice);
3816     const uint32_t viewArraySize =
3817         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D)         ? (1) :
3818         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)   ? (baseLevel.getHeight() - viewTypeBaseSlice) :
3819         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D)         ? (1) :
3820         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)   ? (baseLevel.getDepth() - viewTypeBaseSlice) :
3821         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)         ? (1) :
3822         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)       ? (6) :
3823         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() -
3824                                                            viewTypeBaseSlice) // cube: numFaces * numLayers
3825                                                           :
3826                                                           (0);
3827 
3828     DE_ASSERT(viewArraySize > 0);
3829 
3830     const vk::VkImageSubresourceRange resourceRange = {
3831         vk::VK_IMAGE_ASPECT_COLOR_BIT,             // aspectMask
3832         baseMipLevel,                              // baseMipLevel
3833         sourceImage.getNumLevels() - baseMipLevel, // mipLevels
3834         viewTypeBaseSlice,                         // baseArraySlice
3835         viewArraySize,                             // arraySize
3836     };
3837     const vk::VkImageViewCreateInfo createInfo = {
3838         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
3839         DE_NULL,
3840         (vk::VkImageViewCreateFlags)0,
3841         image,                                       // image
3842         viewType,                                    // viewType
3843         vk::mapTextureFormat(baseLevel.getFormat()), // format
3844         {vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B,
3845          vk::VK_COMPONENT_SWIZZLE_A}, // channels
3846         resourceRange,                // subresourceRange
3847     };
3848     return vk::createImageView(vki, device, &createInfo);
3849 }
3850 
populateSourceImage(tcu::TextureLevelPyramid * dst,vk::VkImageViewType viewType,int imageNdx)3851 void ImageInstanceImages::populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx)
3852 {
3853     const int numLevels = dst->getNumLevels();
3854 
3855     for (int level = 0; level < numLevels; ++level)
3856     {
3857         const int width  = IMAGE_SIZE >> level;
3858         const int height = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3859                                (ARRAY_SIZE) :
3860                                (IMAGE_SIZE >> level);
3861         const int depth =
3862             (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) :
3863             (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE) :
3864             (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3865                                                                                                      (6 * ARRAY_SIZE) :
3866             (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level) :
3867                                                       (1);
3868 
3869         dst->allocLevel(level, width, height, depth);
3870 
3871         {
3872             const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
3873 
3874             for (int z = 0; z < depth; ++z)
3875                 for (int y = 0; y < height; ++y)
3876                     for (int x = 0; x < width; ++x)
3877                     {
3878                         const int gradPos = x + y + z;
3879                         const int gradMax = width + height + depth - 3;
3880 
3881                         int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors)
3882                         int green =
3883                             ((gradPos % 2 == 0) ? (127) : (0)) +
3884                             ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
3885                         int blue =
3886                             (128 * level / numLevels) +
3887                             ((imageNdx % 2 == 0) ? 127 : 0); //!< level and image index (detects incorrect lod / image)
3888 
3889                         DE_ASSERT(de::inRange(red, 0, 255));
3890                         DE_ASSERT(de::inRange(green, 0, 255));
3891                         DE_ASSERT(de::inRange(blue, 0, 255));
3892 
3893                         if (imageNdx % 3 == 0)
3894                             red = 255 - red;
3895                         if (imageNdx % 4 == 0)
3896                             green = 255 - green;
3897                         if (imageNdx % 5 == 0)
3898                             blue = 255 - blue;
3899 
3900                         levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3901                     }
3902         }
3903     }
3904 }
3905 
uploadImage(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkImage image,vk::VkImageLayout layout,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & data)3906 void ImageInstanceImages::uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3907                                       vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image,
3908                                       vk::VkImageLayout layout, vk::VkImageViewType viewType,
3909                                       const tcu::TextureLevelPyramid &data)
3910 {
3911     const uint32_t arraySize =
3912         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3913         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3914                                                   (6 * (uint32_t)ARRAY_SIZE) :
3915                                                   ((uint32_t)ARRAY_SIZE);
3916     const uint32_t dataBufferSize                 = getTextureLevelPyramidDataSize(data);
3917     const vk::VkBufferCreateInfo bufferCreateInfo = {
3918         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3919         DE_NULL,
3920         0u,                                   // flags
3921         dataBufferSize,                       // size
3922         vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
3923         vk::VK_SHARING_MODE_EXCLUSIVE,        // sharingMode
3924         0u,                                   // queueFamilyCount
3925         DE_NULL,                              // pQueueFamilyIndices
3926     };
3927 
3928     const vk::Unique<vk::VkBuffer> dataBuffer(vk::createBuffer(vki, device, &bufferCreateInfo));
3929     const de::MovePtr<vk::Allocation> dataBufferMemory =
3930         allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3931     std::vector<vk::VkBufferImageCopy> copySlices;
3932     // copy data to buffer
3933     writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, viewType, &copySlices);
3934     flushAlloc(vki, device, *dataBufferMemory);
3935 
3936     // copy buffer to image
3937     copyBufferToImage(vki, device, queue, queueFamilyIndex, *dataBuffer, dataBufferSize, copySlices, DE_NULL,
3938                       vk::VK_IMAGE_ASPECT_COLOR_BIT, data.getNumLevels(), arraySize, image, layout);
3939 }
3940 
3941 class ImageFetchInstanceImages : private ImageInstanceImages
3942 {
3943 public:
3944     ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3945                              vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3946                              DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3947                              vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
3948                              uint32_t baseArraySlice);
3949 
3950     static tcu::IVec3 getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
3951                                   int fetchPosNdx);
3952 
3953     tcu::Vec4 fetchImageValue(int fetchPosNdx, int setNdx) const;
3954 
getSourceImage(int ndx) const3955     inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
3956     {
3957         return m_sourceImage[ndx];
3958     }
getImageView(int ndx) const3959     inline vk::VkImageView getImageView(int ndx) const
3960     {
3961         return **m_imageView[ndx % m_imageView.size()];
3962     }
3963 
3964 private:
3965     enum
3966     {
3967         // some arbitrary sample points for all four quadrants
3968         SAMPLE_POINT_0_X = 6,
3969         SAMPLE_POINT_0_Y = 13,
3970         SAMPLE_POINT_0_Z = 49,
3971 
3972         SAMPLE_POINT_1_X = 51,
3973         SAMPLE_POINT_1_Y = 40,
3974         SAMPLE_POINT_1_Z = 44,
3975 
3976         SAMPLE_POINT_2_X = 42,
3977         SAMPLE_POINT_2_Y = 26,
3978         SAMPLE_POINT_2_Z = 19,
3979 
3980         SAMPLE_POINT_3_X = 25,
3981         SAMPLE_POINT_3_Y = 25,
3982         SAMPLE_POINT_3_Z = 18,
3983     };
3984 
3985     const ShaderInputInterface m_shaderInterface;
3986 };
3987 
ImageFetchInstanceImages(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t numLevels,uint32_t baseMipLevel,uint32_t baseArraySlice)3988 ImageFetchInstanceImages::ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3989                                                    uint32_t queueFamilyIndex, vk::VkQueue queue,
3990                                                    vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3991                                                    DescriptorSetCount descriptorSetCount,
3992                                                    ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
3993                                                    uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice)
3994     : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
3995                           getDescriptorSetCount(descriptorSetCount) *
3996                               getInterfaceNumResources(shaderInterface), // numImages
3997                           numLevels, baseMipLevel, baseArraySlice)
3998     , m_shaderInterface(shaderInterface)
3999 {
4000 }
4001 
isImageViewTypeArray(vk::VkImageViewType type)4002 bool isImageViewTypeArray(vk::VkImageViewType type)
4003 {
4004     return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
4005            type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
4006 }
4007 
getFetchPos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int fetchPosNdx)4008 tcu::IVec3 ImageFetchInstanceImages::getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
4009                                                  uint32_t baseArraySlice, int fetchPosNdx)
4010 {
4011     const tcu::IVec3 fetchPositions[4] = {
4012         tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
4013         tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
4014         tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
4015         tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
4016     };
4017     const tcu::IVec3 coord   = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
4018     const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
4019     const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
4020 
4021     switch (viewType)
4022     {
4023     case vk::VK_IMAGE_VIEW_TYPE_1D:
4024     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
4025         return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
4026     case vk::VK_IMAGE_VIEW_TYPE_2D:
4027     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
4028         return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
4029     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4030     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
4031         return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
4032     case vk::VK_IMAGE_VIEW_TYPE_3D:
4033         return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
4034     default:
4035         DE_FATAL("Impossible");
4036         return tcu::IVec3();
4037     }
4038 }
4039 
fetchImageValue(int fetchPosNdx,int setNdx) const4040 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue(int fetchPosNdx, int setNdx) const
4041 {
4042     DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
4043 
4044     const tcu::TextureLevelPyramid &fetchSrcA = getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface));
4045     const tcu::TextureLevelPyramid &fetchSrcB =
4046         (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
4047             fetchSrcA :
4048             getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
4049     const tcu::TextureLevelPyramid &fetchSrc =
4050         ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
4051     tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
4052 
4053     // add base array layer into the appropriate coordinate, based on the view type
4054     if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
4055         fetchPos.z() += 6 * m_baseArraySlice;
4056     else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
4057         fetchPos.y() += m_baseArraySlice;
4058     else
4059         fetchPos.z() += m_baseArraySlice;
4060 
4061     return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
4062 }
4063 
4064 class ImageFetchRenderInstance : public SingleCmdRenderInstance
4065 {
4066 public:
4067     ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
4068                              vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4069                              vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
4070                              ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4071                              uint32_t baseArraySlice, const bool bind2);
4072 
4073 private:
4074     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
4075         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4076         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4077         DescriptorUpdateMethod updateMethod);
4078 
4079     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
4080         const vk::DeviceInterface &vki, vk::VkDevice device,
4081         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
4082 
4083     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
4084                                                                vk::VkDescriptorType descriptorType,
4085                                                                DescriptorSetCount descriptorSetCount,
4086                                                                ShaderInputInterface shaderInterface);
4087 
4088     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
4089         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4090         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4091         ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
4092         vk::VkDescriptorPool pool, const ImageFetchInstanceImages &images,
4093         vk::DescriptorSetUpdateBuilder &updateBuilder,
4094 #ifndef CTS_USES_VULKANSC
4095         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4096 #endif
4097         std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = DE_NULL);
4098 
4099     static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
4100                                    vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
4101                                    vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool, vk::VkImageView viewA,
4102                                    vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4103                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
4104                                    std::vector<uint32_t> &descriptorsPerSet,
4105                                    DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
4106 
4107 #ifndef CTS_USES_VULKANSC
4108     static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
4109                                                vk::VkDescriptorType descriptorType,
4110                                                ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout,
4111                                                vk::VkDescriptorPool pool, vk::VkImageView viewA, vk::VkImageView viewB,
4112                                                vk::VkDescriptorSet descriptorSet,
4113                                                std::vector<UpdateTemplateHandleSp> &updateTemplates,
4114                                                std::vector<RawUpdateRegistry> &registry, bool withPush = false,
4115                                                vk::VkPipelineLayout pipelineLayout = 0);
4116 #endif
4117 
4118     void logTestPlan(void) const;
4119     vk::VkPipelineLayout getPipelineLayout(void) const;
4120     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
4121     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
4122 
4123     enum
4124     {
4125         RENDER_SIZE = 128,
4126     };
4127 
4128     const DescriptorUpdateMethod m_updateMethod;
4129     const vk::VkDescriptorType m_descriptorType;
4130     const DescriptorSetCount m_descriptorSetCount;
4131     const vk::VkShaderStageFlags m_stageFlags;
4132     const vk::VkShaderStageFlags m_existingStages;
4133     const ShaderInputInterface m_shaderInterface;
4134     const vk::VkImageViewType m_viewType;
4135     const uint32_t m_numLevels;
4136     const uint32_t m_baseMipLevel;
4137     const uint32_t m_baseArraySlice;
4138 
4139 #ifndef CTS_USES_VULKANSC
4140     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4141     std::vector<RawUpdateRegistry> m_updateRegistry;
4142 #endif
4143     vk::DescriptorSetUpdateBuilder m_updateBuilder;
4144     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
4145     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
4146     const ImageFetchInstanceImages m_images;
4147     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
4148     std::vector<uint32_t> m_descriptorsPerSet;
4149     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
4150 };
4151 
ImageFetchRenderInstance(vkt::Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,const bool bind2)4152 ImageFetchRenderInstance::ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4153                                                    bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
4154                                                    DescriptorSetCount descriptorSetCount,
4155                                                    vk::VkShaderStageFlags stageFlags,
4156                                                    vk::VkShaderStageFlags existingStages,
4157                                                    ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4158                                                    uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4159     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
4160     , m_updateMethod(updateMethod)
4161     , m_descriptorType(descriptorType)
4162     , m_descriptorSetCount(descriptorSetCount)
4163     , m_stageFlags(stageFlags)
4164     , m_existingStages(existingStages)
4165     , m_shaderInterface(shaderInterface)
4166     , m_viewType(viewType)
4167     , m_numLevels(baseMipLevel + 1u)
4168     , m_baseMipLevel(baseMipLevel)
4169     , m_baseArraySlice(baseArraySlice)
4170 #ifndef CTS_USES_VULKANSC
4171     , m_updateTemplates()
4172     , m_updateRegistry()
4173 #endif
4174     , m_updateBuilder()
4175     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
4176                                                         m_shaderInterface, m_stageFlags, m_updateMethod))
4177     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
4178     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4179                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4180     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
4181     , m_descriptorsPerSet()
4182     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
4183                                             m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, m_images,
4184                                             m_updateBuilder,
4185 #ifndef CTS_USES_VULKANSC
4186                                             m_updateTemplates, m_updateRegistry,
4187 #endif
4188                                             m_descriptorsPerSet, *m_pipelineLayout))
4189 {
4190 }
4191 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)4192 std::vector<DescriptorSetLayoutHandleSp> ImageFetchRenderInstance::createDescriptorSetLayouts(
4193     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4194     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4195     DescriptorUpdateMethod updateMethod)
4196 {
4197 #ifdef CTS_USES_VULKANSC
4198     DE_UNREF(updateMethod);
4199 #endif
4200     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
4201     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4202 
4203 #ifndef CTS_USES_VULKANSC
4204     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4205         updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4206     {
4207         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4208     }
4209 #endif
4210 
4211     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4212     {
4213         vk::DescriptorSetLayoutBuilder builder;
4214 
4215         switch (shaderInterface)
4216         {
4217         case SHADER_INPUT_SINGLE_DESCRIPTOR:
4218             builder.addSingleBinding(descriptorType, stageFlags);
4219             break;
4220 
4221         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4222             builder.addSingleBinding(descriptorType, stageFlags);
4223             builder.addSingleBinding(descriptorType, stageFlags);
4224             break;
4225 
4226         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4227             builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
4228             builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
4229             break;
4230 
4231         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4232             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
4233             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
4234             break;
4235 
4236         case SHADER_INPUT_DESCRIPTOR_ARRAY:
4237             builder.addArrayBinding(descriptorType, 2u, stageFlags);
4238             break;
4239 
4240         default:
4241             DE_FATAL("Impossible");
4242         }
4243 
4244         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
4245         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
4246 
4247         // Add an empty descriptor set layout between sets 0 and 2
4248         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
4249         {
4250             vk::DescriptorSetLayoutBuilder emptyBuilder;
4251             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
4252                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
4253             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
4254         }
4255     }
4256     return descriptorSetLayouts;
4257 }
4258 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)4259 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout(
4260     const vk::DeviceInterface &vki, vk::VkDevice device,
4261     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
4262 {
4263     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
4264     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
4265         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
4266 
4267     const vk::VkPipelineLayoutCreateInfo createInfo = {
4268         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4269         DE_NULL,
4270         (vk::VkPipelineLayoutCreateFlags)0,
4271         (uint32_t)layoutHandles.size(), // descriptorSetCount
4272         &layoutHandles.front(),         // pSetLayouts
4273         0u,                             // pushConstantRangeCount
4274         DE_NULL,                        // pPushConstantRanges
4275     };
4276     return vk::createPipelineLayout(vki, device, &createInfo);
4277 }
4278 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)4279 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
4280                                                                               vk::VkDevice device,
4281                                                                               vk::VkDescriptorType descriptorType,
4282                                                                               DescriptorSetCount descriptorSetCount,
4283                                                                               ShaderInputInterface shaderInterface)
4284 {
4285     return vk::DescriptorPoolBuilder()
4286         .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
4287         .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4288                getDescriptorSetCount(descriptorSetCount));
4289 }
4290 
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool pool,const ImageFetchInstanceImages & images,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,std::vector<uint32_t> & descriptorsPerSet,vk::VkPipelineLayout pipelineLayout)4291 std::vector<DescriptorSetHandleSp> ImageFetchRenderInstance::createDescriptorSets(
4292     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4293     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
4294     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool,
4295     const ImageFetchInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
4296 #ifndef CTS_USES_VULKANSC
4297     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4298 #endif
4299     std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
4300 {
4301 #ifdef CTS_USES_VULKANSC
4302     DE_UNREF(pipelineLayout);
4303 #endif
4304     std::vector<DescriptorSetHandleSp> descriptorSets;
4305 
4306     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4307     {
4308         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
4309 
4310         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
4311                                                            pool, 1u, &layout};
4312 
4313         vk::VkImageView viewA = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface));
4314         vk::VkImageView viewB = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1);
4315 
4316         vk::Move<vk::VkDescriptorSet> descriptorSet;
4317         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4318             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4319         {
4320             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
4321         }
4322         else
4323         {
4324             descriptorSet = vk::Move<vk::VkDescriptorSet>();
4325         }
4326 
4327 #ifndef CTS_USES_VULKANSC
4328         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4329         {
4330             writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4331                                            *descriptorSet, updateTemplates, updateRegistry);
4332         }
4333         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4334         {
4335             writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4336                                            *descriptorSet, updateTemplates, updateRegistry, true, pipelineLayout);
4337         }
4338         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4339         {
4340             writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4341                                updateBuilder, descriptorsPerSet, updateMethod);
4342         }
4343         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4344 #endif
4345         {
4346             writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4347                                updateBuilder, descriptorsPerSet);
4348         }
4349 
4350         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
4351     }
4352     return descriptorSets;
4353 }
4354 
writeDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkImageView viewA,vk::VkImageView viewB,vk::VkDescriptorSet descriptorSet,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)4355 void ImageFetchRenderInstance::writeDescriptorSet(
4356     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4357     ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4358     vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4359     vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
4360     DescriptorUpdateMethod updateMethod)
4361 {
4362     DE_UNREF(layout);
4363     DE_UNREF(pool);
4364     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(descriptorType);
4365     const vk::VkDescriptorImageInfo imageInfos[2] = {
4366         makeDescriptorImageInfo(viewA, imageLayout),
4367         makeDescriptorImageInfo(viewB, imageLayout),
4368     };
4369     uint32_t numDescriptors = 0u;
4370 
4371     switch (shaderInterface)
4372     {
4373     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4374         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4375                                   &imageInfos[0]);
4376         numDescriptors++;
4377         break;
4378 
4379     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4380         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4381                                   &imageInfos[0]);
4382         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
4383                                   &imageInfos[1]);
4384         numDescriptors += 2;
4385         break;
4386 
4387     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4388         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4389                                   &imageInfos[0]);
4390         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
4391                                   &imageInfos[1]);
4392         numDescriptors += 2;
4393         break;
4394 
4395     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4396         updateBuilder.writeSingle(descriptorSet,
4397                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4398                                   descriptorType, &imageInfos[0]);
4399         updateBuilder.writeSingle(descriptorSet,
4400                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4401                                   descriptorType, &imageInfos[1]);
4402         numDescriptors += 2;
4403         break;
4404 
4405     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4406         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4407                                  2u, imageInfos);
4408         numDescriptors++;
4409         break;
4410 
4411     default:
4412         DE_FATAL("Impossible");
4413     }
4414 
4415     descriptorsPerSet.push_back(numDescriptors);
4416 
4417     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4418     {
4419         updateBuilder.update(vki, device);
4420         updateBuilder.clear();
4421     }
4422 }
4423 
4424 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkImageView viewA,vk::VkImageView viewB,vk::VkDescriptorSet descriptorSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)4425 void ImageFetchRenderInstance::writeDescriptorSetWithTemplate(
4426     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4427     ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4428     vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4429     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
4430     vk::VkPipelineLayout pipelineLayout)
4431 {
4432     DE_UNREF(pool);
4433     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4434     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4435         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4436         DE_NULL,
4437         0,
4438         0,       // updateCount
4439         DE_NULL, // pUpdates
4440         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4441                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4442         layout,
4443         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4444         pipelineLayout,
4445         0};
4446     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(descriptorType);
4447     const vk::VkDescriptorImageInfo imageInfos[2] = {
4448         makeDescriptorImageInfo(viewA, imageLayout),
4449         makeDescriptorImageInfo(viewB, imageLayout),
4450     };
4451 
4452     RawUpdateRegistry updateRegistry;
4453 
4454     updateRegistry.addWriteObject(imageInfos[0]);
4455     updateRegistry.addWriteObject(imageInfos[1]);
4456 
4457     switch (shaderInterface)
4458     {
4459     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4460         updateEntries.push_back(
4461             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4462         break;
4463 
4464     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4465         updateEntries.push_back(
4466             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4467         updateEntries.push_back(
4468             createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4469         break;
4470 
4471     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4472         updateEntries.push_back(
4473             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4474         updateEntries.push_back(
4475             createTemplateBinding(2, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4476         break;
4477 
4478     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4479         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
4480                                                       updateRegistry.getWriteObjectOffset(0), 0));
4481         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
4482                                                       updateRegistry.getWriteObjectOffset(1), 0));
4483         break;
4484 
4485     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4486         updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
4487                                                       sizeof(imageInfos[0])));
4488         break;
4489 
4490     default:
4491         DE_FATAL("Impossible");
4492     }
4493 
4494     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
4495     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
4496 
4497     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
4498         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
4499     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
4500     registry.push_back(updateRegistry);
4501 
4502     if (!withPush)
4503     {
4504         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
4505                                             registry.back().getRawPointer());
4506     }
4507 }
4508 #endif
4509 
logTestPlan(void) const4510 void ImageFetchRenderInstance::logTestPlan(void) const
4511 {
4512     std::ostringstream msg;
4513 
4514     msg << "Rendering 2x2 grid.\n"
4515         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
4516                                                                     "Multiple descriptor sets. ")
4517         << "Each descriptor set contains "
4518         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
4519             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
4520             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4521             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
4522             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
4523                                                                                      (const char *)DE_NULL)
4524         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
4525         << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4526 
4527     if (m_baseMipLevel)
4528         msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4529     if (m_baseArraySlice)
4530         msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4531 
4532     if (m_stageFlags == 0u)
4533     {
4534         msg << "Descriptors are not accessed in any shader stage.\n";
4535     }
4536     else
4537     {
4538         msg << "Color in each cell is fetched using the descriptor(s):\n";
4539 
4540         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4541         {
4542             msg << "Test sample " << resultNdx << ": fetching at position "
4543                 << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4544 
4545             if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4546             {
4547                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4548                 msg << " from descriptor " << srcResourceNdx;
4549             }
4550 
4551             msg << "\n";
4552         }
4553 
4554         msg << "Descriptors are accessed in {"
4555             << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
4556             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
4557             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
4558             << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
4559             << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
4560     }
4561 
4562     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
4563 }
4564 
getPipelineLayout(void) const4565 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout(void) const
4566 {
4567     return *m_pipelineLayout;
4568 }
4569 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const4570 void ImageFetchRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
4571 {
4572     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
4573         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4574     {
4575         std::vector<vk::VkDescriptorSet> sets;
4576         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4577             sets.push_back(**m_descriptorSets[setNdx]);
4578 
4579         switch (m_descriptorSetCount)
4580         {
4581         case DESCRIPTOR_SET_COUNT_SINGLE:
4582         case DESCRIPTOR_SET_COUNT_MULTIPLE:
4583         {
4584             bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4585                                getPipelineLayout(), 0, (int)sets.size(), &sets.front(), 0, DE_NULL, m_bind2);
4586             break;
4587         }
4588         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
4589         {
4590             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4591             {
4592                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
4593                 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4594                                    getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], 0, DE_NULL, m_bind2);
4595             }
4596             break;
4597         }
4598         default:
4599             DE_FATAL("Impossible");
4600         }
4601     }
4602 #ifndef CTS_USES_VULKANSC
4603     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4604     {
4605         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4606             m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
4607                                                       getDescriptorSetNdx(m_descriptorSetCount, setNdx),
4608                                                       (const void *)m_updateRegistry[setNdx].getRawPointer());
4609     }
4610     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4611     {
4612         uint32_t descriptorNdx = 0u;
4613         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4614         {
4615             const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
4616             m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
4617                                            getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
4618                                            numDescriptors);
4619             descriptorNdx += numDescriptors;
4620         }
4621     }
4622 #endif
4623 
4624     m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
4625 }
4626 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const4627 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
4628 {
4629     const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
4630     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4631     const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
4632     const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
4633 
4634     tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
4635 
4636     tcu::Vec4 sample0 = tcu::Vec4(0.0f);
4637     tcu::Vec4 sample1 = tcu::Vec4(0.0f);
4638     tcu::Vec4 sample2 = tcu::Vec4(0.0f);
4639     tcu::Vec4 sample3 = tcu::Vec4(0.0f);
4640 
4641     for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
4642     {
4643         sample0 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(0, setNdx));
4644         sample1 += (!doFetch) ? (green) : (m_images.fetchImageValue(1, setNdx));
4645         sample2 += (!doFetch) ? (green) : (m_images.fetchImageValue(2, setNdx));
4646         sample3 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(3, setNdx));
4647     }
4648 
4649     if (numDescriptorSets > 1)
4650     {
4651         sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
4652         sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
4653         sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
4654         sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
4655     }
4656 
4657     drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4658 
4659     if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
4660                          result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
4661         return tcu::TestStatus::fail("Image verification failed");
4662     else
4663         return tcu::TestStatus::pass("Pass");
4664 }
4665 
4666 class ImageFetchComputeInstance : public vkt::TestInstance
4667 {
4668 public:
4669     ImageFetchComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4670                               vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4671                               ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4672                               uint32_t baseArraySlice, const bool bind2);
4673 
4674 private:
4675     vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
4676     vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
4677     vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
4678                                                       uint32_t setNdx);
4679     void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
4680 #ifndef CTS_USES_VULKANSC
4681     void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
4682                                         uint32_t setNdx, bool withPush = false,
4683                                         vk::VkPipelineLayout pipelineLayout = DE_NULL);
4684 #endif
4685 
4686     tcu::TestStatus iterate(void);
4687     void logTestPlan(void) const;
4688     tcu::TestStatus testResourceAccess(void);
4689 
4690     const DescriptorUpdateMethod m_updateMethod;
4691     const vk::VkDescriptorType m_descriptorType;
4692     const DescriptorSetCount m_descriptorSetCount;
4693     const ShaderInputInterface m_shaderInterface;
4694     const vk::VkImageViewType m_viewType;
4695     const uint32_t m_numLevels;
4696     const uint32_t m_baseMipLevel;
4697     const uint32_t m_baseArraySlice;
4698     const bool m_bind2;
4699 #ifndef CTS_USES_VULKANSC
4700     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4701 #endif
4702     const vk::DeviceInterface &m_vki;
4703     const vk::VkDevice m_device;
4704     const vk::VkQueue m_queue;
4705     const uint32_t m_queueFamilyIndex;
4706     vk::Allocator &m_allocator;
4707     const ComputeInstanceResultBuffer m_result;
4708     const ImageFetchInstanceImages m_images;
4709 #ifndef CTS_USES_VULKANSC
4710     std::vector<RawUpdateRegistry> m_updateRegistry;
4711 #endif
4712     vk::DescriptorSetUpdateBuilder m_updateBuilder;
4713     std::vector<uint32_t> m_descriptorsPerSet;
4714 };
4715 
ImageFetchComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,const bool bind2)4716 ImageFetchComputeInstance::ImageFetchComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
4717                                                      vk::VkDescriptorType descriptorType,
4718                                                      DescriptorSetCount descriptorSetCount,
4719                                                      ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4720                                                      uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4721     : vkt::TestInstance(context)
4722     , m_updateMethod(updateMethod)
4723     , m_descriptorType(descriptorType)
4724     , m_descriptorSetCount(descriptorSetCount)
4725     , m_shaderInterface(shaderInterface)
4726     , m_viewType(viewType)
4727     , m_numLevels(baseMipLevel + 1u)
4728     , m_baseMipLevel(baseMipLevel)
4729     , m_baseArraySlice(baseArraySlice)
4730     , m_bind2(bind2)
4731 #ifndef CTS_USES_VULKANSC
4732     , m_updateTemplates()
4733 #endif
4734     , m_vki(context.getDeviceInterface())
4735     , m_device(context.getDevice())
4736     , m_queue(context.getUniversalQueue())
4737     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
4738     , m_allocator(context.getDefaultAllocator())
4739     , m_result(m_vki, m_device, m_allocator)
4740     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4741                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4742 #ifndef CTS_USES_VULKANSC
4743     , m_updateRegistry()
4744 #endif
4745     , m_updateBuilder()
4746     , m_descriptorsPerSet()
4747 {
4748 }
4749 
createDescriptorSetLayout(uint32_t setNdx) const4750 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
4751 {
4752     vk::DescriptorSetLayoutBuilder builder;
4753     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4754     uint32_t binding                                = 0;
4755 
4756 #ifndef CTS_USES_VULKANSC
4757     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4758         m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4759     {
4760         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4761     }
4762 #endif
4763 
4764     if (setNdx == 0)
4765         builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
4766                                         binding++);
4767 
4768     switch (m_shaderInterface)
4769     {
4770     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4771         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4772         break;
4773 
4774     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4775         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4776         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4777         break;
4778 
4779     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4780         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding);
4781         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2);
4782         break;
4783 
4784     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4785         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
4786         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
4787         break;
4788 
4789     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4790         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4791         break;
4792 
4793     default:
4794         DE_FATAL("Impossible");
4795     }
4796 
4797     return builder.build(m_vki, m_device, extraFlags);
4798 }
4799 
createDescriptorPool(void) const4800 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool(void) const
4801 {
4802     return vk::DescriptorPoolBuilder()
4803         .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4804         .addType(m_descriptorType,
4805                  getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
4806         .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4807                getDescriptorSetCount(m_descriptorSetCount));
4808 }
4809 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)4810 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
4811                                                                              vk::VkDescriptorSetLayout layout,
4812                                                                              uint32_t setNdx)
4813 {
4814     const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
4815                                                        pool, 1u, &layout};
4816 
4817     vk::Move<vk::VkDescriptorSet> descriptorSet;
4818     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4819         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4820     {
4821         descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
4822     }
4823     else
4824     {
4825         descriptorSet = vk::Move<vk::VkDescriptorSet>();
4826     }
4827 
4828 #ifndef CTS_USES_VULKANSC
4829     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4830     {
4831         writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx);
4832     }
4833     else
4834 #endif
4835         if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4836     {
4837         writeDescriptorSet(*descriptorSet, setNdx);
4838     }
4839 
4840     return descriptorSet;
4841 }
4842 
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)4843 void ImageFetchComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
4844 {
4845     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4846         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4847     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(m_descriptorType);
4848     const vk::VkDescriptorImageInfo imageInfos[2] = {
4849         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4850                                 imageLayout),
4851         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4852                                 imageLayout),
4853     };
4854 
4855     uint32_t binding        = 0u;
4856     uint32_t numDescriptors = 0u;
4857 
4858     // result
4859     if (setNdx == 0)
4860     {
4861         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4862                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4863         numDescriptors++;
4864     }
4865 
4866     // images
4867     switch (m_shaderInterface)
4868     {
4869     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4870         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4871                                     m_descriptorType, &imageInfos[0]);
4872         numDescriptors++;
4873         break;
4874 
4875     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4876         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4877                                     m_descriptorType, &imageInfos[0]);
4878         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4879                                     m_descriptorType, &imageInfos[1]);
4880         numDescriptors += 2;
4881         break;
4882 
4883     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4884         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
4885                                     m_descriptorType, &imageInfos[0]);
4886         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
4887                                     m_descriptorType, &imageInfos[1]);
4888         numDescriptors += 2;
4889         break;
4890 
4891     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4892         m_updateBuilder.writeSingle(descriptorSet,
4893                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4894                                     m_descriptorType, &imageInfos[0]);
4895         m_updateBuilder.writeSingle(descriptorSet,
4896                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4897                                     m_descriptorType, &imageInfos[1]);
4898         numDescriptors += 2;
4899         break;
4900 
4901     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4902         m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4903                                    m_descriptorType, 2u, imageInfos);
4904         numDescriptors++;
4905         break;
4906 
4907     default:
4908         DE_FATAL("Impossible");
4909     }
4910 
4911     m_descriptorsPerSet.push_back(numDescriptors);
4912 
4913     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4914     {
4915         m_updateBuilder.update(m_vki, m_device);
4916         m_updateBuilder.clear();
4917     }
4918 }
4919 
4920 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)4921 void ImageFetchComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
4922                                                                vk::VkDescriptorSetLayout layout, uint32_t setNdx,
4923                                                                bool withPush, vk::VkPipelineLayout pipelineLayout)
4924 {
4925     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4926         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4927     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(m_descriptorType);
4928     const vk::VkDescriptorImageInfo imageInfos[2] = {
4929         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4930                                 imageLayout),
4931         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4932                                 imageLayout),
4933     };
4934     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4935     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4936         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4937         DE_NULL,
4938         0,
4939         0,       // updateCount
4940         DE_NULL, // pUpdates
4941         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4942                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4943         layout,
4944         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
4945         pipelineLayout,
4946         setNdx};
4947 
4948     uint32_t binding = 0u;
4949     uint32_t offset  = 0u;
4950     RawUpdateRegistry updateRegistry;
4951 
4952     if (setNdx == 0)
4953         updateRegistry.addWriteObject(resultInfo);
4954 
4955     updateRegistry.addWriteObject(imageInfos[0]);
4956     updateRegistry.addWriteObject(imageInfos[1]);
4957 
4958     // result
4959     if (setNdx == 0)
4960         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
4961                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4962 
4963     // images
4964     switch (m_shaderInterface)
4965     {
4966     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4967         updateEntries.push_back(
4968             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4969         break;
4970 
4971     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4972         updateEntries.push_back(
4973             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4974         updateEntries.push_back(
4975             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4976         break;
4977 
4978     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4979         updateEntries.push_back(
4980             createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4981         updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
4982                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4983         break;
4984 
4985     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4986         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
4987                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4988         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
4989                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4990         break;
4991 
4992     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4993         updateEntries.push_back(createTemplateBinding(
4994             binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(imageInfos[0])));
4995         break;
4996 
4997     default:
4998         DE_FATAL("Impossible");
4999     }
5000 
5001     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
5002     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
5003 
5004     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
5005         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
5006     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
5007     m_updateRegistry.push_back(updateRegistry);
5008 
5009     if (!withPush)
5010     {
5011         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
5012                                               m_updateRegistry.back().getRawPointer());
5013     }
5014 }
5015 #endif
5016 
iterate(void)5017 tcu::TestStatus ImageFetchComputeInstance::iterate(void)
5018 {
5019     logTestPlan();
5020     return testResourceAccess();
5021 }
5022 
logTestPlan(void) const5023 void ImageFetchComputeInstance::logTestPlan(void) const
5024 {
5025     std::ostringstream msg;
5026 
5027     msg << "Fetching 4 values from image in compute shader.\n"
5028         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
5029                                                                     "Multiple descriptor sets. ")
5030         << "Each descriptor set contains "
5031         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
5032             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
5033             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
5034             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
5035             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
5036                                                                                      (const char *)DE_NULL)
5037         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5038         << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
5039 
5040     if (m_baseMipLevel)
5041         msg << "Image view base mip level = " << m_baseMipLevel << "\n";
5042     if (m_baseArraySlice)
5043         msg << "Image view base array slice = " << m_baseArraySlice << "\n";
5044 
5045     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5046     {
5047         msg << "Test sample " << resultNdx << ": fetch at position "
5048             << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
5049 
5050         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5051         {
5052             const int srcResourceNdx = (resultNdx % 2); // ABAB source
5053             msg << " from descriptor " << srcResourceNdx;
5054         }
5055 
5056         msg << "\n";
5057     }
5058 
5059     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
5060 }
5061 
testResourceAccess(void)5062 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess(void)
5063 {
5064     const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
5065     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5066     std::vector<DescriptorSetHandleSp> descriptorSets;
5067     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5068     std::vector<vk::VkDescriptorSet> setHandles;
5069 
5070     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5071     {
5072         vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
5073         vk::Move<vk::VkDescriptorSet> set          = createDescriptorSet(*descriptorPool, *layout, setNdx);
5074 
5075         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5076         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
5077 
5078         layoutHandles.push_back(**descriptorSetLayouts.back());
5079         setHandles.push_back(**descriptorSets.back());
5080 
5081         // Add an empty descriptor set layout between sets 0 and 2
5082         if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5083         {
5084             vk::DescriptorSetLayoutBuilder emptyBuilder;
5085             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5086                 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5087 
5088             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5089             layoutHandles.push_back(**descriptorSetLayouts.back());
5090         }
5091     }
5092 
5093     const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
5094                                    &layoutHandles.front());
5095     const uint32_t *const dynamicOffsets                = DE_NULL;
5096     const int numDynamicOffsets                         = 0;
5097     const vk::VkBufferMemoryBarrier *const preBarriers  = DE_NULL;
5098     const int numPreBarriers                            = 0;
5099     const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
5100     const int numPostBarriers                           = 1;
5101 
5102     const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
5103                                  tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
5104                                  numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
5105                                  postBarriers, m_bind2);
5106 
5107     tcu::Vec4 results[4];
5108     bool anyResultSet = false;
5109     bool allResultsOk = true;
5110 
5111 #ifndef CTS_USES_VULKANSC
5112     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5113     {
5114         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5115             writeDescriptorSetWithTemplate(DE_NULL, layoutHandles[setNdx], setNdx, true, pipeline.getPipelineLayout());
5116 
5117         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
5118     }
5119     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5120     {
5121         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5122             writeDescriptorSet(DE_NULL, setNdx);
5123 
5124         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
5125     }
5126     else
5127 #endif
5128     {
5129         compute.submitAndWait(m_queueFamilyIndex, m_queue);
5130     }
5131     m_result.readResultContentsTo(&results);
5132 
5133     // verify
5134     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5135     {
5136         const tcu::Vec4 result = results[resultNdx];
5137 
5138         tcu::Vec4 reference = tcu::Vec4(0.0f);
5139         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5140             reference += m_images.fetchImageValue(resultNdx, setNdx);
5141 
5142         if (getDescriptorSetCount(m_descriptorSetCount) > 1)
5143             reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
5144 
5145         const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
5146 
5147         if (result != tcu::Vec4(-1.0f))
5148             anyResultSet = true;
5149 
5150         if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5151         {
5152             allResultsOk = false;
5153 
5154             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
5155                                                 << reference << ", got " << result << tcu::TestLog::EndMessage;
5156         }
5157     }
5158 
5159     // read back and verify
5160     if (allResultsOk)
5161         return tcu::TestStatus::pass("Pass");
5162     else if (anyResultSet)
5163         return tcu::TestStatus::fail("Invalid result values");
5164     else
5165     {
5166         m_context.getTestContext().getLog()
5167             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
5168         return tcu::TestStatus::fail("Result buffer was not written to");
5169     }
5170 }
5171 
5172 class ImageSampleInstanceImages : private ImageInstanceImages
5173 {
5174 public:
5175     ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
5176                               vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5177                               DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5178                               vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
5179                               uint32_t baseArraySlice, bool immutable);
5180 
5181     static std::vector<tcu::Sampler> getRefSamplers(DescriptorSetCount descriptorSetCount,
5182                                                     ShaderInputInterface shaderInterface);
5183 
5184     static std::vector<SamplerHandleSp> getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5185                                                     std::vector<tcu::Sampler> &refSamplers,
5186                                                     const tcu::TextureFormat imageFormat);
5187 
5188     static tcu::Vec4 getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
5189                                   int samplePosNdx);
5190     tcu::Vec4 fetchSampleValue(int samplePosNdx, int setNdx) const;
5191 
getSourceImage(int ndx) const5192     inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
5193     {
5194         return m_sourceImage[ndx % m_sourceImage.size()];
5195     }
getImageView(int ndx) const5196     inline vk::VkImageView getImageView(int ndx) const
5197     {
5198         return **m_imageView[ndx % m_imageView.size()];
5199     }
getRefSampler(int ndx) const5200     inline tcu::Sampler getRefSampler(int ndx) const
5201     {
5202         return m_refSampler[ndx % m_refSampler.size()];
5203     }
getSampler(int ndx) const5204     inline vk::VkSampler getSampler(int ndx) const
5205     {
5206         return **m_sampler[ndx % m_sampler.size()];
5207     }
isImmutable(void) const5208     inline bool isImmutable(void) const
5209     {
5210         return m_isImmutable;
5211     }
5212 
5213 private:
5214     static int getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5215                             ShaderInputInterface shaderInterface);
5216     static tcu::Sampler createRefSampler(int ndx);
5217     static vk::Move<vk::VkSampler> createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5218                                                  const tcu::Sampler &sampler, const tcu::TextureFormat &format);
5219 
5220     static tcu::Texture1DArrayView getRef1DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5221                                                 uint32_t baseArraySlice,
5222                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5223     static tcu::Texture2DArrayView getRef2DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5224                                                 uint32_t baseArraySlice,
5225                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5226     static tcu::Texture3DView getRef3DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5227                                            uint32_t baseArraySlice,
5228                                            std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5229     static tcu::TextureCubeArrayView getRefCubeView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5230                                                     uint32_t baseArraySlice,
5231                                                     std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5232 
5233     const vk::VkDescriptorType m_descriptorType;
5234     const ShaderInputInterface m_shaderInterface;
5235     const bool m_isImmutable;
5236 
5237     std::vector<tcu::Sampler> m_refSampler;
5238     std::vector<SamplerHandleSp> m_sampler;
5239 };
5240 
ImageSampleInstanceImages(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex,vk::VkQueue queue,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t numLevels,uint32_t baseMipLevel,uint32_t baseArraySlice,bool immutable)5241 ImageSampleInstanceImages::ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
5242                                                      uint32_t queueFamilyIndex, vk::VkQueue queue,
5243                                                      vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5244                                                      DescriptorSetCount descriptorSetCount,
5245                                                      ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5246                                                      uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice,
5247                                                      bool immutable)
5248     : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
5249                           getNumImages(descriptorType, descriptorSetCount, shaderInterface), numLevels, baseMipLevel,
5250                           baseArraySlice)
5251     , m_descriptorType(descriptorType)
5252     , m_shaderInterface(shaderInterface)
5253     , m_isImmutable(immutable)
5254     , m_refSampler(getRefSamplers(descriptorSetCount, shaderInterface))
5255     , m_sampler(getSamplers(vki, device, m_refSampler, m_imageFormat))
5256 {
5257 }
5258 
getRefSamplers(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5259 std::vector<tcu::Sampler> ImageSampleInstanceImages::getRefSamplers(DescriptorSetCount descriptorSetCount,
5260                                                                     ShaderInputInterface shaderInterface)
5261 {
5262     std::vector<tcu::Sampler> refSamplers;
5263     for (uint32_t samplerNdx = 0;
5264          samplerNdx < getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
5265          samplerNdx++)
5266         refSamplers.push_back(createRefSampler(samplerNdx));
5267 
5268     return refSamplers;
5269 }
5270 
getSamplers(const vk::DeviceInterface & vki,vk::VkDevice device,std::vector<tcu::Sampler> & refSamplers,const tcu::TextureFormat imageFormat)5271 std::vector<SamplerHandleSp> ImageSampleInstanceImages::getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5272                                                                     std::vector<tcu::Sampler> &refSamplers,
5273                                                                     const tcu::TextureFormat imageFormat)
5274 {
5275     std::vector<SamplerHandleSp> samplers;
5276     for (uint32_t samplerNdx = 0; samplerNdx < (uint32_t)refSamplers.size(); samplerNdx++)
5277     {
5278         vk::Move<vk::VkSampler> sampler = createSampler(vki, device, refSamplers[samplerNdx], imageFormat);
5279         samplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
5280     }
5281     return samplers;
5282 }
5283 
getSamplePos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int samplePosNdx)5284 tcu::Vec4 ImageSampleInstanceImages::getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
5285                                                   uint32_t baseArraySlice, int samplePosNdx)
5286 {
5287     DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5288 
5289     const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
5290     const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
5291 
5292     // choose arbitrary values that are not ambiguous with NEAREST filtering
5293 
5294     switch (viewType)
5295     {
5296     case vk::VK_IMAGE_VIEW_TYPE_1D:
5297     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5298     case vk::VK_IMAGE_VIEW_TYPE_2D:
5299     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5300     case vk::VK_IMAGE_VIEW_TYPE_3D:
5301     {
5302         const tcu::Vec3 coords[4] = {
5303             tcu::Vec3(0.75f, 0.5f, (float)(12u % imageSize) + 0.25f),
5304 
5305             tcu::Vec3((float)(23u % imageSize) + 0.25f, (float)(73u % imageSize) + 0.5f,
5306                       (float)(16u % imageSize) + 0.5f + (float)imageSize),
5307 
5308             tcu::Vec3(-(float)(43u % imageSize) + 0.25f, (float)(84u % imageSize) + 0.5f + (float)imageSize,
5309                       (float)(117u % imageSize) + 0.75f),
5310 
5311             tcu::Vec3((float)imageSize + 0.5f, (float)(75u % imageSize) + 0.25f,
5312                       (float)(83u % imageSize) + 0.25f + (float)imageSize),
5313         };
5314         const uint32_t slices[4] = {
5315             0u % arraySize,
5316             4u % arraySize,
5317             9u % arraySize,
5318             2u % arraySize,
5319         };
5320 
5321         switch (viewType)
5322         {
5323         case vk::VK_IMAGE_VIEW_TYPE_1D:
5324         case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5325             return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, (float)slices[samplePosNdx], 0.0f, 0.0f);
5326         case vk::VK_IMAGE_VIEW_TYPE_2D:
5327         case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5328             return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5329                              (float)slices[samplePosNdx], 0.0f);
5330         case vk::VK_IMAGE_VIEW_TYPE_3D:
5331             return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5332                              coords[samplePosNdx].z() / (float)imageSize, 0.0f);
5333         default:
5334             DE_FATAL("Impossible");
5335             return tcu::Vec4();
5336         }
5337     }
5338 
5339     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5340     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5341     {
5342         // \note these values are in [0, texSize]*3 space for convenience
5343         const tcu::Vec3 coords[4] = {
5344             tcu::Vec3(0.75f, 0.5f, (float)imageSize),
5345 
5346             tcu::Vec3((float)(13u % imageSize) + 0.25f, 0.0f, (float)(16u % imageSize) + 0.5f),
5347 
5348             tcu::Vec3(0.0f, (float)(84u % imageSize) + 0.5f, (float)(10u % imageSize) + 0.75f),
5349 
5350             tcu::Vec3((float)imageSize, (float)(75u % imageSize) + 0.25f, (float)(83u % imageSize) + 0.75f),
5351         };
5352         const uint32_t slices[4] = {
5353             1u % arraySize,
5354             2u % arraySize,
5355             9u % arraySize,
5356             5u % arraySize,
5357         };
5358 
5359         DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
5360         DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
5361         DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
5362 
5363         // map to [-1, 1]*3 space
5364         return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
5365                          coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
5366                          coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f, (float)slices[samplePosNdx]);
5367     }
5368 
5369     default:
5370         DE_FATAL("Impossible");
5371         return tcu::Vec4();
5372     }
5373 }
5374 
fetchSampleValue(int samplePosNdx,int setNdx) const5375 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue(int samplePosNdx, int setNdx) const
5376 {
5377     DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5378 
5379     // texture order is ABAB
5380     const bool isSamplerCase                   = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
5381     const uint32_t numImages                   = (isSamplerCase) ? 1 : getInterfaceNumResources(m_shaderInterface);
5382     const tcu::TextureLevelPyramid &sampleSrcA = getSourceImage(setNdx * numImages);
5383     const tcu::TextureLevelPyramid &sampleSrcB =
5384         (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? sampleSrcA : getSourceImage(setNdx * numImages + 1);
5385     const tcu::TextureLevelPyramid &sampleSrc = (isSamplerCase)           ? (sampleSrcA) :
5386                                                 ((samplePosNdx % 2) == 0) ? (sampleSrcA) :
5387                                                                             (sampleSrcB);
5388 
5389     // sampler order is ABAB
5390     const tcu::Sampler &samplerA = getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface));
5391     const tcu::Sampler &samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
5392                                        (samplerA) :
5393                                        getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
5394     const tcu::Sampler &sampler  = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
5395 
5396     const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5397     const float lod           = 0.0f;
5398     std::vector<tcu::ConstPixelBufferAccess> levelStorage;
5399 
5400     switch (m_viewType)
5401     {
5402     case vk::VK_IMAGE_VIEW_TYPE_1D:
5403     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5404         return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5405             .sample(sampler, samplePos.x(), samplePos.y(), lod);
5406     case vk::VK_IMAGE_VIEW_TYPE_2D:
5407     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5408         return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5409             .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5410     case vk::VK_IMAGE_VIEW_TYPE_3D:
5411         return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5412             .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5413     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5414     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5415         return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5416             .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod);
5417 
5418     default:
5419     {
5420         DE_FATAL("Impossible");
5421         return tcu::Vec4();
5422     }
5423     }
5424 }
5425 
getNumImages(vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5426 int ImageSampleInstanceImages::getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5427                                             ShaderInputInterface shaderInterface)
5428 {
5429     // If we are testing separate samplers, just one image is enough
5430     if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5431         return getDescriptorSetCount(descriptorSetCount);
5432     else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5433     {
5434         // combined: numImages == numSamplers
5435         return getInterfaceNumResources(shaderInterface) * getDescriptorSetCount(descriptorSetCount);
5436     }
5437     else
5438     {
5439         DE_FATAL("Impossible");
5440         return 0;
5441     }
5442 }
5443 
createRefSampler(int ndx)5444 tcu::Sampler ImageSampleInstanceImages::createRefSampler(int ndx)
5445 {
5446     if (ndx % 2 == 0)
5447     {
5448         // linear, wrapping
5449         return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
5450                             tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5451                             tcu::Vec4(0.0f), true);
5452     }
5453     else
5454     {
5455         // nearest, clamping
5456         return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
5457                             tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5458                             tcu::Vec4(0.0f), true);
5459     }
5460 }
5461 
createSampler(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::Sampler & sampler,const tcu::TextureFormat & format)5462 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5463                                                                  const tcu::Sampler &sampler,
5464                                                                  const tcu::TextureFormat &format)
5465 {
5466     const vk::VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, format);
5467 
5468     return vk::createSampler(vki, device, &createInfo);
5469 }
5470 
getRef1DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5471 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView(const tcu::TextureLevelPyramid &source,
5472                                                                 uint32_t baseMipLevel, uint32_t baseArraySlice,
5473                                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5474 {
5475     DE_ASSERT(levelStorage->empty());
5476 
5477     const uint32_t numSlices = (uint32_t)source.getLevel(0).getHeight();
5478     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5479 
5480     // cut pyramid from baseMipLevel
5481     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5482     {
5483         // cut levels from baseArraySlice
5484         const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5485         const tcu::ConstPixelBufferAccess cutLevel =
5486             tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
5487         levelStorage->push_back(cutLevel);
5488     }
5489 
5490     return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
5491 }
5492 
getRef2DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5493 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView(const tcu::TextureLevelPyramid &source,
5494                                                                 uint32_t baseMipLevel, uint32_t baseArraySlice,
5495                                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5496 {
5497     DE_ASSERT(levelStorage->empty());
5498 
5499     const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth();
5500     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5501 
5502     // cut pyramid from baseMipLevel
5503     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5504     {
5505         // cut levels from baseArraySlice
5506         const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5507         const tcu::ConstPixelBufferAccess cutLevel =
5508             tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(),
5509                               numSlices - baseArraySlice);
5510         levelStorage->push_back(cutLevel);
5511     }
5512 
5513     return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
5514 }
5515 
getRef3DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5516 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView(const tcu::TextureLevelPyramid &source,
5517                                                            uint32_t baseMipLevel, uint32_t baseArraySlice,
5518                                                            std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5519 {
5520     DE_ASSERT(levelStorage->empty());
5521     DE_ASSERT(baseArraySlice == 0);
5522     DE_UNREF(baseArraySlice);
5523 
5524     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5525 
5526     // cut pyramid from baseMipLevel
5527     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5528         levelStorage->push_back(source.getLevel(level));
5529 
5530     return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
5531 }
5532 
getRefCubeView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5533 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView(
5534     const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel, uint32_t baseArraySlice,
5535     std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5536 {
5537     DE_ASSERT(levelStorage->empty());
5538 
5539     const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth() / 6;
5540     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5541 
5542     // cut pyramid from baseMipLevel
5543     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5544     {
5545         // cut levels from baseArraySlice
5546         const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5547         const tcu::ConstPixelBufferAccess cutLevel =
5548             tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(),
5549                               (numSlices - baseArraySlice) * 6);
5550         levelStorage->push_back(cutLevel);
5551     }
5552 
5553     return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
5554 }
5555 
5556 class ImageSampleRenderInstance : public SingleCmdRenderInstance
5557 {
5558 public:
5559     ImageSampleRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5560                               vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5561                               vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
5562                               ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
5563                               uint32_t baseArraySlice, bool isImmutable, const bool bind2);
5564 
5565 private:
5566     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
5567         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5568         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5569         const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod);
5570 
5571     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
5572         const vk::DeviceInterface &vki, vk::VkDevice device,
5573         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
5574 
5575     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
5576                                                                vk::VkDescriptorType descriptorType,
5577                                                                DescriptorSetCount descriptorSetCount,
5578                                                                ShaderInputInterface shaderInterface);
5579 
5580     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
5581         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5582         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5583         ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
5584         vk::VkDescriptorPool pool, bool isImmutable, const ImageSampleInstanceImages &images,
5585         vk::DescriptorSetUpdateBuilder &updateBuilder,
5586 #ifndef CTS_USES_VULKANSC
5587         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5588 #endif
5589         std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = DE_NULL);
5590 
5591     static void writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5592                                           ShaderInputInterface shaderInterface, bool isImmutable,
5593                                           const ImageSampleInstanceImages &images, vk::VkDescriptorSet descriptorSet,
5594                                           uint32_t setNdx, vk::DescriptorSetUpdateBuilder &updateBuilder,
5595                                           std::vector<uint32_t> &descriptorsPerSet,
5596                                           DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5597 
5598     static void writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5599                                                ShaderInputInterface shaderInterface, bool isImmutable,
5600                                                const ImageSampleInstanceImages &images,
5601                                                vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5602                                                vk::DescriptorSetUpdateBuilder &updateBuilder,
5603                                                std::vector<uint32_t> &descriptorsPerSet,
5604                                                DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5605 
5606     static void writeSamplerDescriptorSetWithTemplate(
5607         const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5608         ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5609         vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5610 #ifndef CTS_USES_VULKANSC
5611         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry,
5612 #endif
5613         bool withPush = false, vk::VkPipelineLayout pipelineLayout = 0);
5614 
5615     static void writeImageSamplerDescriptorSetWithTemplate(
5616         const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5617         ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5618         vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5619 #ifndef CTS_USES_VULKANSC
5620         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry,
5621 #endif
5622         bool withPush = false, vk::VkPipelineLayout pipelineLayout = 0);
5623 
5624     void logTestPlan(void) const;
5625     vk::VkPipelineLayout getPipelineLayout(void) const;
5626     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
5627     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
5628 
5629     enum
5630     {
5631         RENDER_SIZE = 128,
5632     };
5633 
5634     const DescriptorUpdateMethod m_updateMethod;
5635     const vk::VkDescriptorType m_descriptorType;
5636     const DescriptorSetCount m_descriptorSetCount;
5637     const vk::VkShaderStageFlags m_stageFlags;
5638     const vk::VkShaderStageFlags m_existingStages;
5639     const ShaderInputInterface m_shaderInterface;
5640     const vk::VkImageViewType m_viewType;
5641     const uint32_t m_numLevels;
5642     const uint32_t m_baseMipLevel;
5643     const uint32_t m_baseArraySlice;
5644 
5645 #ifndef CTS_USES_VULKANSC
5646     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
5647     std::vector<RawUpdateRegistry> m_updateRegistry;
5648 #endif
5649     vk::DescriptorSetUpdateBuilder m_updateBuilder;
5650     const ImageSampleInstanceImages m_images;
5651     std::vector<uint32_t> m_descriptorsPerSet;
5652     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
5653     const vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
5654     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
5655     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
5656 };
5657 
ImageSampleRenderInstance(vkt::Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,bool isImmutable,const bool bind2)5658 ImageSampleRenderInstance::ImageSampleRenderInstance(
5659     vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5660     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, vk::VkShaderStageFlags stageFlags,
5661     vk::VkShaderStageFlags existingStages, ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5662     uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutable, const bool bind2)
5663     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
5664     , m_updateMethod(updateMethod)
5665     , m_descriptorType(descriptorType)
5666     , m_descriptorSetCount(descriptorSetCount)
5667     , m_stageFlags(stageFlags)
5668     , m_existingStages(existingStages)
5669     , m_shaderInterface(shaderInterface)
5670     , m_viewType(viewType)
5671     , m_numLevels(baseMipLevel + 1u)
5672     , m_baseMipLevel(baseMipLevel)
5673     , m_baseArraySlice(baseArraySlice)
5674 #ifndef CTS_USES_VULKANSC
5675     , m_updateTemplates()
5676     , m_updateRegistry()
5677 #endif
5678     , m_updateBuilder()
5679     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
5680                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice, isImmutable)
5681     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
5682                                                         m_shaderInterface, m_stageFlags, m_images, m_updateMethod))
5683     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
5684     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
5685     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
5686                                             m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, isImmutable,
5687                                             m_images, m_updateBuilder,
5688 #ifndef CTS_USES_VULKANSC
5689                                             m_updateTemplates, m_updateRegistry,
5690 #endif
5691                                             m_descriptorsPerSet, *m_pipelineLayout))
5692 {
5693 }
5694 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,const ImageSampleInstanceImages & images,DescriptorUpdateMethod updateMethod)5695 std::vector<DescriptorSetLayoutHandleSp> ImageSampleRenderInstance::createDescriptorSetLayouts(
5696     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5697     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5698     const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod)
5699 {
5700 #ifdef CTS_USES_VULKANSC
5701     DE_UNREF(updateMethod);
5702 #endif
5703     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5704 
5705     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5706     {
5707         const vk::VkSampler samplers[2] = {
5708             images.getSampler(setNdx * getInterfaceNumResources(shaderInterface)),
5709             images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1),
5710         };
5711 
5712         vk::DescriptorSetLayoutBuilder builder;
5713         const bool addSeparateImage                     = descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
5714         vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
5715 
5716 #ifndef CTS_USES_VULKANSC
5717         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
5718             updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5719         {
5720             extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
5721         }
5722 #endif
5723 
5724         // (combined)samplers follow
5725         switch (shaderInterface)
5726         {
5727         case SHADER_INPUT_SINGLE_DESCRIPTOR:
5728             if (addSeparateImage)
5729                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5730             builder.addSingleSamplerBinding(descriptorType, stageFlags,
5731                                             (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5732             break;
5733 
5734         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5735             if (addSeparateImage)
5736                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5737             builder.addSingleSamplerBinding(descriptorType, stageFlags,
5738                                             (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5739             builder.addSingleSamplerBinding(descriptorType, stageFlags,
5740                                             (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
5741             break;
5742 
5743         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5744             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 0u,
5745                                                    (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5746             if (addSeparateImage)
5747                 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags, 1u);
5748             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 2u,
5749                                                    (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
5750             break;
5751 
5752         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5753             if (addSeparateImage)
5754                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5755             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0),
5756                                                    (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
5757             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1),
5758                                                    (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
5759             break;
5760 
5761         case SHADER_INPUT_DESCRIPTOR_ARRAY:
5762             if (addSeparateImage)
5763                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5764             builder.addArraySamplerBinding(descriptorType, 2u, stageFlags,
5765                                            (images.isImmutable()) ? (samplers) : (DE_NULL));
5766             break;
5767 
5768         default:
5769             DE_FATAL("Impossible");
5770         }
5771 
5772         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
5773         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5774 
5775         // Add an empty descriptor set layout between sets 0 and 2
5776         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5777         {
5778             vk::DescriptorSetLayoutBuilder emptyBuilder;
5779             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5780                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5781             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5782         }
5783     }
5784 
5785     return descriptorSetLayouts;
5786 }
5787 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)5788 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout(
5789     const vk::DeviceInterface &vki, vk::VkDevice device,
5790     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
5791 {
5792     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5793     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
5794         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
5795 
5796     const vk::VkPipelineLayoutCreateInfo createInfo = {
5797         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5798         DE_NULL,
5799         (vk::VkPipelineLayoutCreateFlags)0,
5800         (uint32_t)layoutHandles.size(), // descriptorSetCount
5801         &layoutHandles.front(),         // pSetLayouts
5802         0u,                             // pushConstantRangeCount
5803         DE_NULL,                        // pPushConstantRanges
5804     };
5805     return vk::createPipelineLayout(vki, device, &createInfo);
5806 }
5807 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5808 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
5809                                                                                vk::VkDevice device,
5810                                                                                vk::VkDescriptorType descriptorType,
5811                                                                                DescriptorSetCount descriptorSetCount,
5812                                                                                ShaderInputInterface shaderInterface)
5813 {
5814     vk::DescriptorPoolBuilder builder;
5815 
5816     if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5817     {
5818         // separate samplers need image to sample
5819         builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, getDescriptorSetCount(descriptorSetCount));
5820 
5821         // also need sample to use, indifferent of whether immutable or not
5822         builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER,
5823                         getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5824     }
5825     else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5826     {
5827         // combined image samplers
5828         builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5829                         getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5830     }
5831     else
5832         DE_FATAL("Impossible");
5833 
5834     return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5835                          getDescriptorSetCount(descriptorSetCount));
5836 }
5837 
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool pool,bool isImmutable,const ImageSampleInstanceImages & images,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,std::vector<uint32_t> & descriptorsPerSet,vk::VkPipelineLayout pipelineLayout)5838 std::vector<DescriptorSetHandleSp> ImageSampleRenderInstance::createDescriptorSets(
5839     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5840     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5841     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool, bool isImmutable,
5842     const ImageSampleInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
5843 #ifndef CTS_USES_VULKANSC
5844     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5845 #endif
5846     std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
5847 {
5848 #ifdef CTS_USES_VULKANSC
5849     DE_UNREF(pipelineLayout);
5850 #endif
5851     std::vector<DescriptorSetHandleSp> descriptorSets;
5852 
5853     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5854     {
5855         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
5856 
5857         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
5858                                                            pool, 1u, &layout};
5859 
5860         vk::Move<vk::VkDescriptorSet> descriptorSet;
5861         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
5862             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5863         {
5864             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
5865         }
5866         else
5867         {
5868             descriptorSet = vk::Move<vk::VkDescriptorSet>();
5869         }
5870 
5871 #ifndef CTS_USES_VULKANSC
5872         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
5873         {
5874             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5875                 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5876                                                       images, *descriptorSet, setNdx, layout, updateTemplates,
5877                                                       updateRegistry);
5878             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5879                 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5880                                                            isImmutable, images, *descriptorSet, setNdx, layout,
5881                                                            updateTemplates, updateRegistry);
5882             else
5883                 DE_FATAL("Impossible");
5884         }
5885         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5886         {
5887             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5888                 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5889                                                       images, DE_NULL, setNdx, layout, updateTemplates, updateRegistry,
5890                                                       true, pipelineLayout);
5891             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5892                 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5893                                                            isImmutable, images, DE_NULL, setNdx, layout,
5894                                                            updateTemplates, updateRegistry, true, pipelineLayout);
5895             else
5896                 DE_FATAL("Impossible");
5897         }
5898         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5899         {
5900             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5901                 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5902                                           updateBuilder, descriptorsPerSet, updateMethod);
5903             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5904                 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5905                                                setNdx, updateBuilder, descriptorsPerSet, updateMethod);
5906             else
5907                 DE_FATAL("Impossible");
5908         }
5909         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
5910 #endif
5911         {
5912             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5913                 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5914                                           updateBuilder, descriptorsPerSet);
5915             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5916                 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5917                                                setNdx, updateBuilder, descriptorsPerSet);
5918             else
5919                 DE_FATAL("Impossible");
5920         }
5921 
5922         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
5923     }
5924     return descriptorSets;
5925 }
5926 
writeSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)5927 void ImageSampleRenderInstance::writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5928                                                           ShaderInputInterface shaderInterface, bool isImmutable,
5929                                                           const ImageSampleInstanceImages &images,
5930                                                           vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5931                                                           vk::DescriptorSetUpdateBuilder &updateBuilder,
5932                                                           std::vector<uint32_t> &descriptorsPerSet,
5933                                                           DescriptorUpdateMethod updateMethod)
5934 {
5935     const vk::VkDescriptorImageInfo imageInfo =
5936         makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
5937     vk::VkDescriptorImageInfo samplersInfos[2] = {
5938         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
5939         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
5940     };
5941 
5942     if (isImmutable)
5943     {
5944         samplersInfos[0].sampler = VK_NULL_HANDLE;
5945         samplersInfos[1].sampler = VK_NULL_HANDLE;
5946     }
5947 
5948     const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
5949     uint32_t numDescriptors        = 1u;
5950 
5951     // stand alone texture
5952     updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation),
5953                               vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
5954 
5955     // samplers
5956     if (!isImmutable || (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH))
5957     {
5958         switch (shaderInterface)
5959         {
5960         case SHADER_INPUT_SINGLE_DESCRIPTOR:
5961             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5962                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5963             numDescriptors++;
5964             break;
5965 
5966         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5967             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5968                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5969             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5970                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5971             numDescriptors += 2;
5972             break;
5973 
5974         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5975             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
5976                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5977             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5978                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5979             numDescriptors += 2;
5980             break;
5981 
5982         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5983             updateBuilder.writeSingle(descriptorSet,
5984                                       vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
5985                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5986             updateBuilder.writeSingle(descriptorSet,
5987                                       vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
5988                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5989             numDescriptors += 2;
5990             break;
5991 
5992         case SHADER_INPUT_DESCRIPTOR_ARRAY:
5993             updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5994                                      vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
5995             numDescriptors++;
5996             break;
5997 
5998         default:
5999             DE_FATAL("Impossible");
6000         }
6001     }
6002 
6003     descriptorsPerSet.push_back(numDescriptors);
6004 
6005     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6006     {
6007         updateBuilder.update(vki, device);
6008         updateBuilder.clear();
6009     }
6010 }
6011 
writeImageSamplerDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)6012 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
6013                                                                ShaderInputInterface shaderInterface, bool isImmutable,
6014                                                                const ImageSampleInstanceImages &images,
6015                                                                vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
6016                                                                vk::DescriptorSetUpdateBuilder &updateBuilder,
6017                                                                std::vector<uint32_t> &descriptorsPerSet,
6018                                                                DescriptorUpdateMethod updateMethod)
6019 {
6020     const vk::VkSampler samplers[2] = {
6021         (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6022             (0) :
6023             (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6024         (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6025             (0) :
6026             (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6027     };
6028     const vk::VkDescriptorImageInfo imageSamplers[2] = {
6029         vk::makeDescriptorImageInfo(samplers[0],
6030                                     images.getImageView(setNdx * getInterfaceNumResources(shaderInterface)),
6031                                     vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6032         vk::makeDescriptorImageInfo(samplers[1],
6033                                     images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1),
6034                                     vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6035     };
6036     uint32_t numDescriptors = 0u;
6037 
6038     // combined image samplers
6039     switch (shaderInterface)
6040     {
6041     case SHADER_INPUT_SINGLE_DESCRIPTOR:
6042         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6043                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6044         numDescriptors++;
6045         break;
6046 
6047     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6048         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6049                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6050         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
6051                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6052         numDescriptors += 2;
6053         break;
6054 
6055     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6056         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6057                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6058         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
6059                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6060         numDescriptors += 2;
6061         break;
6062 
6063     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6064         updateBuilder.writeSingle(descriptorSet,
6065                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6066                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6067         updateBuilder.writeSingle(descriptorSet,
6068                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6069                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6070         numDescriptors += 2;
6071         break;
6072 
6073     case SHADER_INPUT_DESCRIPTOR_ARRAY:
6074         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6075                                  vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
6076         numDescriptors++;
6077         break;
6078 
6079     default:
6080         DE_FATAL("Impossible");
6081     }
6082 
6083     descriptorsPerSet.push_back(numDescriptors);
6084 
6085     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6086     {
6087         updateBuilder.update(vki, device);
6088         updateBuilder.clear();
6089     }
6090 }
6091 
6092 #ifndef CTS_USES_VULKANSC
writeSamplerDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkDescriptorSetLayout layout,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)6093 void ImageSampleRenderInstance::writeSamplerDescriptorSetWithTemplate(
6094     const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6095     ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6096     vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6097     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
6098     vk::VkPipelineLayout pipelineLayout)
6099 {
6100     const vk::VkDescriptorImageInfo imageInfo =
6101         makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6102     const vk::VkDescriptorImageInfo samplersInfos[2] = {
6103         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6104         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6105     };
6106 
6107     const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
6108 
6109     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6110     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6111         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6112         DE_NULL,
6113         0,
6114         0,       // updateCount
6115         DE_NULL, // pUpdates
6116         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6117                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6118         layout,
6119         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6120         pipelineLayout,
6121         getDescriptorSetNdx(descriptorSetCount, setNdx)};
6122 
6123     RawUpdateRegistry updateRegistry;
6124 
6125     updateRegistry.addWriteObject(imageInfo);
6126     updateRegistry.addWriteObject(samplersInfos[0]);
6127     updateRegistry.addWriteObject(samplersInfos[1]);
6128 
6129     // stand alone texture
6130     updateEntries.push_back(createTemplateBinding(samplerLocation, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6131                                                   updateRegistry.getWriteObjectOffset(0), 0));
6132 
6133     // samplers
6134     if (!isImmutable || withPush)
6135     {
6136         switch (shaderInterface)
6137         {
6138         case SHADER_INPUT_SINGLE_DESCRIPTOR:
6139             updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6140                                                           updateRegistry.getWriteObjectOffset(1), 0));
6141             break;
6142 
6143         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6144             updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6145                                                           updateRegistry.getWriteObjectOffset(1), 0));
6146             updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6147                                                           updateRegistry.getWriteObjectOffset(2), 0));
6148             break;
6149 
6150         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6151             updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6152                                                           updateRegistry.getWriteObjectOffset(1), 0));
6153             updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6154                                                           updateRegistry.getWriteObjectOffset(2), 0));
6155             break;
6156 
6157         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6158             updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6159                                                           vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6160                                                           updateRegistry.getWriteObjectOffset(1), 0));
6161             updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6162                                                           vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6163                                                           updateRegistry.getWriteObjectOffset(2), 0));
6164             break;
6165 
6166         case SHADER_INPUT_DESCRIPTOR_ARRAY:
6167             updateEntries.push_back(createTemplateBinding(1, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6168                                                           updateRegistry.getWriteObjectOffset(1),
6169                                                           sizeof(samplersInfos[0])));
6170             break;
6171 
6172         default:
6173             DE_FATAL("Impossible");
6174         }
6175     }
6176 
6177     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
6178     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6179 
6180     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6181         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
6182     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6183     registry.push_back(updateRegistry);
6184 
6185     if (!withPush)
6186     {
6187         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
6188                                             registry.back().getRawPointer());
6189     }
6190 }
6191 
writeImageSamplerDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool isImmutable,const ImageSampleInstanceImages & images,vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkDescriptorSetLayout layout,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)6192 void ImageSampleRenderInstance::writeImageSamplerDescriptorSetWithTemplate(
6193     const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6194     ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6195     vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6196     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
6197     vk::VkPipelineLayout pipelineLayout)
6198 {
6199     const vk::VkSampler samplers[2] = {
6200         (isImmutable && !withPush) ? (0) : (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6201         (isImmutable && !withPush) ? (0) : (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6202     };
6203     const vk::VkDescriptorImageInfo imageSamplers[2] = {
6204         vk::makeDescriptorImageInfo(samplers[0],
6205                                     images.getImageView(setNdx * getInterfaceNumResources(shaderInterface)),
6206                                     vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6207         vk::makeDescriptorImageInfo(samplers[1],
6208                                     images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1),
6209                                     vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6210     };
6211 
6212     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6213     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6214         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6215         DE_NULL,
6216         0,
6217         0,       // updateCount
6218         DE_NULL, // pUpdates
6219         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6220                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6221         layout,
6222         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6223         pipelineLayout,
6224         getDescriptorSetNdx(descriptorSetCount, setNdx)};
6225 
6226     RawUpdateRegistry updateRegistry;
6227 
6228     updateRegistry.addWriteObject(imageSamplers[0]);
6229     updateRegistry.addWriteObject(imageSamplers[1]);
6230 
6231     // combined image samplers
6232     switch (shaderInterface)
6233     {
6234     case SHADER_INPUT_SINGLE_DESCRIPTOR:
6235         updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6236                                                       updateRegistry.getWriteObjectOffset(0), 0));
6237         break;
6238 
6239     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6240         updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6241                                                       updateRegistry.getWriteObjectOffset(0), 0));
6242         updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6243                                                       updateRegistry.getWriteObjectOffset(1), 0));
6244         break;
6245 
6246     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6247         updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6248                                                       updateRegistry.getWriteObjectOffset(0), 0));
6249         updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6250                                                       updateRegistry.getWriteObjectOffset(1), 0));
6251         break;
6252 
6253     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6254         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6255                                                       vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6256                                                       updateRegistry.getWriteObjectOffset(0), 0));
6257         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6258                                                       vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6259                                                       updateRegistry.getWriteObjectOffset(1), 0));
6260         break;
6261 
6262     case SHADER_INPUT_DESCRIPTOR_ARRAY:
6263         updateEntries.push_back(createTemplateBinding(0, 0, 2, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
6264                                                       updateRegistry.getWriteObjectOffset(0),
6265                                                       sizeof(imageSamplers[0])));
6266         break;
6267 
6268     default:
6269         DE_FATAL("Impossible");
6270     }
6271 
6272     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
6273     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6274 
6275     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6276         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
6277     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6278     registry.push_back(updateRegistry);
6279 
6280     if (!withPush)
6281     {
6282         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
6283                                             registry.back().getRawPointer());
6284     }
6285 }
6286 #endif
6287 
logTestPlan(void) const6288 void ImageSampleRenderInstance::logTestPlan(void) const
6289 {
6290     std::ostringstream msg;
6291 
6292     msg << "Rendering 2x2 grid.\n";
6293 
6294     if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6295     {
6296         msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
6297                                                                         "Multiple descriptor sets. ")
6298             << "Each descriptor set contains "
6299             << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
6300                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
6301                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
6302                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
6303                 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
6304                                                                                          (const char *)DE_NULL)
6305             << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
6306     }
6307     else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6308     {
6309         msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
6310                                                                         "Multiple descriptor sets. ")
6311             << "Each descriptor set contains "
6312             << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
6313                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
6314                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
6315                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
6316                 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
6317                                                                                          (const char *)DE_NULL)
6318             << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
6319     }
6320     else
6321         DE_FATAL("Impossible");
6322 
6323     msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
6324 
6325     if (m_baseMipLevel)
6326         msg << "Image view base mip level = " << m_baseMipLevel << "\n";
6327     if (m_baseArraySlice)
6328         msg << "Image view base array slice = " << m_baseArraySlice << "\n";
6329 
6330     if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
6331         msg << "Sampler mode is LINEAR, with WRAP\n";
6332     else
6333         msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
6334 
6335     if (m_stageFlags == 0u)
6336     {
6337         msg << "Descriptors are not accessed in any shader stage.\n";
6338     }
6339     else
6340     {
6341         msg << "Color in each cell is fetched using the descriptor(s):\n";
6342 
6343         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
6344         {
6345             msg << "Test sample " << resultNdx << ": sample at position "
6346                 << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
6347 
6348             if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
6349             {
6350                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
6351 
6352                 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6353                     msg << " using sampler " << srcResourceNdx;
6354                 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6355                     msg << " from combined image sampler " << srcResourceNdx;
6356                 else
6357                     DE_FATAL("Impossible");
6358             }
6359             msg << "\n";
6360         }
6361 
6362         msg << "Descriptors are accessed in {"
6363             << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
6364             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
6365             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
6366             << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
6367             << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
6368     }
6369 
6370     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
6371 }
6372 
getPipelineLayout(void) const6373 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout(void) const
6374 {
6375     return *m_pipelineLayout;
6376 }
6377 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const6378 void ImageSampleRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
6379 {
6380     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
6381         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6382     {
6383         std::vector<vk::VkDescriptorSet> setHandles;
6384         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6385             setHandles.push_back(**m_descriptorSets[setNdx]);
6386 
6387         switch (m_descriptorSetCount)
6388         {
6389         case DESCRIPTOR_SET_COUNT_SINGLE:
6390         case DESCRIPTOR_SET_COUNT_MULTIPLE:
6391         {
6392             bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6393                                getPipelineLayout(), 0u, (int)setHandles.size(), &setHandles.front(), 0u, DE_NULL,
6394                                m_bind2);
6395             break;
6396         }
6397         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
6398         {
6399             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6400             {
6401                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
6402                 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6403                                    getPipelineLayout(), descriptorSetNdx, 1u, &setHandles[setNdx], 0u, DE_NULL,
6404                                    m_bind2);
6405             }
6406             break;
6407         }
6408         default:
6409             DE_FATAL("Impossible");
6410         }
6411     }
6412 #ifndef CTS_USES_VULKANSC
6413     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
6414     {
6415         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6416         {
6417             const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
6418             m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
6419                                                       descriptorSetNdx,
6420                                                       (const void *)m_updateRegistry[setNdx].getRawPointer());
6421         }
6422     }
6423     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6424     {
6425         uint32_t descriptorNdx = 0u;
6426         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
6427         {
6428             const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
6429             const uint32_t numDescriptors   = m_descriptorsPerSet[setNdx];
6430             m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
6431                                            descriptorSetNdx, descriptorNdx, numDescriptors);
6432             descriptorNdx += numDescriptors;
6433         }
6434     }
6435 #endif
6436 
6437     m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
6438 }
6439 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const6440 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
6441 {
6442     const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
6443     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
6444     const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
6445     const bool doFetch        = (m_stageFlags != 0u); // no active stages? Then don't fetch
6446     const tcu::RGBA threshold = tcu::RGBA(
6447         8, 8, 8, 8); // source image is high-frequency so the threshold is quite large to tolerate sampling errors
6448 
6449     tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
6450 
6451     tcu::Vec4 sample0 = tcu::Vec4(0.0f);
6452     tcu::Vec4 sample1 = tcu::Vec4(0.0f);
6453     tcu::Vec4 sample2 = tcu::Vec4(0.0f);
6454     tcu::Vec4 sample3 = tcu::Vec4(0.0f);
6455 
6456     for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
6457     {
6458         sample0 += (!doFetch) ? (yellow) : (m_images.fetchSampleValue(0, setNdx));
6459         sample1 += (!doFetch) ? (green) : (m_images.fetchSampleValue(1, setNdx));
6460         sample2 += (!doFetch) ? (green) : (m_images.fetchSampleValue(2, setNdx));
6461         sample3 += (!doFetch) ? (yellow) : (m_images.fetchSampleValue(3, setNdx));
6462     }
6463 
6464     if (numDescriptorSets > 1)
6465     {
6466         sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
6467         sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
6468         sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
6469         sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
6470     }
6471 
6472     drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
6473 
6474     if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
6475                          result, threshold, tcu::COMPARE_LOG_RESULT))
6476         return tcu::TestStatus::fail("Image verification failed");
6477     else
6478         return tcu::TestStatus::pass("Pass");
6479 }
6480 
6481 class ImageSampleComputeInstance : public vkt::TestInstance
6482 {
6483 public:
6484     ImageSampleComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
6485                                vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
6486                                ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
6487                                uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutableSampler,
6488                                const bool bind2);
6489 
6490 private:
6491     vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
6492     vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
6493     vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
6494                                                       uint32_t setNdx);
6495     void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, uint32_t setNdx,
6496                             vk::VkPipelineLayout pipelineLayout = DE_NULL);
6497     void writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
6498 #ifndef CTS_USES_VULKANSC
6499     void writeImageSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
6500                                                     uint32_t setNdx, bool withPush = false,
6501                                                     vk::VkPipelineLayout pipelineLayout = DE_NULL);
6502 #endif
6503     void writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
6504 #ifndef CTS_USES_VULKANSC
6505     void writeSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
6506                                                uint32_t setNdx, bool withPush = false,
6507                                                vk::VkPipelineLayout pipelineLayout = DE_NULL);
6508 #endif
6509 
6510     tcu::TestStatus iterate(void);
6511     void logTestPlan(void) const;
6512     tcu::TestStatus testResourceAccess(void);
6513 
6514     const DescriptorUpdateMethod m_updateMethod;
6515     const vk::VkDescriptorType m_descriptorType;
6516     const DescriptorSetCount m_descriptorSetCount;
6517     const ShaderInputInterface m_shaderInterface;
6518     const vk::VkImageViewType m_viewType;
6519     const uint32_t m_numLevels;
6520     const uint32_t m_baseMipLevel;
6521     const uint32_t m_baseArraySlice;
6522     const bool m_isImmutableSampler;
6523     const bool m_bind2;
6524 #ifndef CTS_USES_VULKANSC
6525     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
6526 #endif
6527 
6528     const vk::DeviceInterface &m_vki;
6529     const vk::VkDevice m_device;
6530     const vk::VkQueue m_queue;
6531     const uint32_t m_queueFamilyIndex;
6532     vk::Allocator &m_allocator;
6533     const ComputeInstanceResultBuffer m_result;
6534     const ImageSampleInstanceImages m_images;
6535 #ifndef CTS_USES_VULKANSC
6536     std::vector<RawUpdateRegistry> m_updateRegistry;
6537 #endif
6538     vk::DescriptorSetUpdateBuilder m_updateBuilder;
6539     std::vector<uint32_t> m_descriptorsPerSet;
6540 };
6541 
ImageSampleComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,bool isImmutableSampler,const bool bind2)6542 ImageSampleComputeInstance::ImageSampleComputeInstance(
6543     Context &context, DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
6544     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
6545     uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutableSampler, const bool bind2)
6546     : vkt::TestInstance(context)
6547     , m_updateMethod(updateMethod)
6548     , m_descriptorType(descriptorType)
6549     , m_descriptorSetCount(descriptorSetCount)
6550     , m_shaderInterface(shaderInterface)
6551     , m_viewType(viewType)
6552     , m_numLevels(baseMipLevel + 1u)
6553     , m_baseMipLevel(baseMipLevel)
6554     , m_baseArraySlice(baseArraySlice)
6555     , m_isImmutableSampler(isImmutableSampler)
6556     , m_bind2(bind2)
6557 #ifndef CTS_USES_VULKANSC
6558     , m_updateTemplates()
6559 #endif
6560     , m_vki(context.getDeviceInterface())
6561     , m_device(context.getDevice())
6562     , m_queue(context.getUniversalQueue())
6563     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
6564     , m_allocator(context.getDefaultAllocator())
6565     , m_result(m_vki, m_device, m_allocator)
6566     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
6567                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
6568 #ifndef CTS_USES_VULKANSC
6569     , m_updateRegistry()
6570 #endif
6571     , m_updateBuilder()
6572     , m_descriptorsPerSet()
6573 {
6574 }
6575 
createDescriptorSetLayout(uint32_t setNdx) const6576 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
6577 {
6578     const vk::VkSampler samplers[2] = {
6579         m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface)),
6580         m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
6581     };
6582 
6583     vk::DescriptorSetLayoutBuilder builder;
6584     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
6585     uint32_t binding                                = 0;
6586 
6587 #ifndef CTS_USES_VULKANSC
6588     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
6589         m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6590     {
6591         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
6592     }
6593 #endif
6594 
6595     // result buffer
6596     if (setNdx == 0)
6597         builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6598                                         binding++);
6599 
6600     // (combined)samplers follow
6601     switch (m_shaderInterface)
6602     {
6603     case SHADER_INPUT_SINGLE_DESCRIPTOR:
6604         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6605             builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6606                                             binding++);
6607         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6608                                                (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
6609         break;
6610 
6611     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6612         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6613             builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6614                                             binding++);
6615         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6616                                                (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
6617         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6618                                                (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
6619         break;
6620 
6621     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6622         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding,
6623                                                (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
6624         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6625             builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6626                                             binding + 1u);
6627         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2u,
6628                                                (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
6629         break;
6630 
6631     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6632         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6633             builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6634                                             binding++);
6635         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6636                                                getArbitraryBindingIndex(0),
6637                                                (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
6638         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6639                                                getArbitraryBindingIndex(1),
6640                                                (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
6641         break;
6642 
6643     case SHADER_INPUT_DESCRIPTOR_ARRAY:
6644         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6645             builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6646                                             binding++);
6647         builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6648                                        (m_images.isImmutable()) ? (samplers) : (DE_NULL));
6649         break;
6650 
6651     default:
6652         DE_FATAL("Impossible");
6653     }
6654 
6655     return builder.build(m_vki, m_device, extraFlags);
6656 }
6657 
createDescriptorPool(void) const6658 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool(void) const
6659 {
6660     vk::DescriptorPoolBuilder builder;
6661 
6662     builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
6663     builder.addType(m_descriptorType,
6664                     getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface));
6665 
6666     if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6667         builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, getDescriptorSetCount(m_descriptorSetCount));
6668 
6669     return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
6670                          getDescriptorSetCount(m_descriptorSetCount));
6671 }
6672 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)6673 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
6674                                                                               vk::VkDescriptorSetLayout layout,
6675                                                                               uint32_t setNdx)
6676 {
6677     const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
6678                                                        pool, 1u, &layout};
6679 
6680     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
6681         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6682     {
6683         vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
6684         writeDescriptorSet(*descriptorSet, layout, setNdx);
6685 
6686         return descriptorSet;
6687     }
6688 
6689     return vk::Move<vk::VkDescriptorSet>();
6690 }
6691 
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkPipelineLayout pipelineLayout)6692 void ImageSampleComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
6693                                                     uint32_t setNdx, vk::VkPipelineLayout pipelineLayout)
6694 {
6695 #ifdef CTS_USES_VULKANSC
6696     DE_UNREF(layout);
6697     DE_UNREF(pipelineLayout);
6698 #else
6699     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
6700     {
6701         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6702             writeSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx);
6703         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6704             writeImageSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx);
6705         else
6706             DE_FATAL("Impossible");
6707     }
6708     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
6709     {
6710         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6711             writeSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx, true, pipelineLayout);
6712         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6713             writeImageSamplerDescriptorSetWithTemplate(descriptorSet, layout, setNdx, true, pipelineLayout);
6714         else
6715             DE_FATAL("Impossible");
6716     }
6717     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
6718     {
6719         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6720             writeSamplerDescriptorSet(descriptorSet, setNdx);
6721         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6722             writeImageSamplerDescriptorSet(descriptorSet, setNdx);
6723         else
6724             DE_FATAL("Impossible");
6725     }
6726     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6727 #endif
6728     {
6729         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
6730             writeSamplerDescriptorSet(descriptorSet, setNdx);
6731         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
6732             writeImageSamplerDescriptorSet(descriptorSet, setNdx);
6733         else
6734             DE_FATAL("Impossible");
6735     }
6736 }
6737 
writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)6738 void ImageSampleComputeInstance::writeSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
6739 {
6740     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
6741         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
6742     const vk::VkDescriptorImageInfo imageInfo =
6743         makeDescriptorImageInfo(m_images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6744     const vk::VkDescriptorImageInfo samplersInfos[2] = {
6745         makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6746         makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
6747     };
6748     uint32_t binding        = 0u;
6749     uint32_t numDescriptors = 0u;
6750 
6751     // result
6752     if (setNdx == 0)
6753     {
6754         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6755                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
6756         numDescriptors++;
6757     }
6758 
6759     // stand alone texture
6760     {
6761         const uint32_t texutreBinding =
6762             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? (binding + 1) : (binding++);
6763         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(texutreBinding),
6764                                     vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
6765         numDescriptors++;
6766     }
6767 
6768     // samplers
6769     if (!m_isImmutableSampler || (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH))
6770     {
6771         switch (m_shaderInterface)
6772         {
6773         case SHADER_INPUT_SINGLE_DESCRIPTOR:
6774             m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6775                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6776             numDescriptors++;
6777             break;
6778 
6779         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6780             m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6781                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6782             m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6783                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
6784             numDescriptors += 2;
6785             break;
6786 
6787         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6788             m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
6789                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6790             m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
6791                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
6792             numDescriptors += 2;
6793             break;
6794 
6795         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6796             m_updateBuilder.writeSingle(descriptorSet,
6797                                         vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6798                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
6799             m_updateBuilder.writeSingle(descriptorSet,
6800                                         vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6801                                         vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
6802             numDescriptors += 2;
6803             break;
6804 
6805         case SHADER_INPUT_DESCRIPTOR_ARRAY:
6806             m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6807                                        vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
6808             numDescriptors++;
6809             break;
6810 
6811         default:
6812             DE_FATAL("Impossible");
6813         }
6814     }
6815 
6816     m_descriptorsPerSet.push_back(numDescriptors);
6817 
6818     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6819     {
6820         m_updateBuilder.update(m_vki, m_device);
6821         m_updateBuilder.clear();
6822     }
6823 }
6824 
6825 #ifndef CTS_USES_VULKANSC
writeSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)6826 void ImageSampleComputeInstance::writeSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
6827                                                                        vk::VkDescriptorSetLayout layout,
6828                                                                        uint32_t setNdx, bool withPush,
6829                                                                        vk::VkPipelineLayout pipelineLayout)
6830 {
6831     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6832     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
6833         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
6834     const vk::VkDescriptorImageInfo imageInfo =
6835         makeDescriptorImageInfo(m_images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6836     const vk::VkDescriptorImageInfo samplersInfos[2] = {
6837         makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6838         makeDescriptorImageInfo(m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
6839     };
6840     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6841         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6842         DE_NULL,
6843         0,
6844         0,       // updateCount
6845         DE_NULL, // pUpdates
6846         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6847                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6848         layout,
6849         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
6850         pipelineLayout,
6851         getDescriptorSetNdx(m_descriptorSetCount, setNdx)};
6852     uint32_t binding = 0u;
6853     uint32_t offset  = 0u;
6854     RawUpdateRegistry updateRegistry;
6855 
6856     if (setNdx == 0)
6857         updateRegistry.addWriteObject(resultInfo);
6858 
6859     updateRegistry.addWriteObject(imageInfo);
6860     updateRegistry.addWriteObject(samplersInfos[0]);
6861     updateRegistry.addWriteObject(samplersInfos[1]);
6862 
6863     // result
6864     if (setNdx == 0)
6865         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
6866                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
6867 
6868     // stand alone texture
6869     {
6870         const uint32_t textureBinding =
6871             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? (binding + 1) : (binding++);
6872         updateEntries.push_back(createTemplateBinding(textureBinding, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6873                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
6874     }
6875 
6876     // samplers
6877     if (!m_isImmutableSampler || withPush)
6878     {
6879         switch (m_shaderInterface)
6880         {
6881         case SHADER_INPUT_SINGLE_DESCRIPTOR:
6882             updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6883                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6884             break;
6885 
6886         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6887             updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6888                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6889             updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6890                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6891             break;
6892 
6893         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6894             updateEntries.push_back(createTemplateBinding(binding, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6895                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6896             updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6897                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6898             break;
6899 
6900         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6901             updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6902                                                           vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6903                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6904             updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6905                                                           vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6906                                                           updateRegistry.getWriteObjectOffset(offset++), 0));
6907             break;
6908 
6909         case SHADER_INPUT_DESCRIPTOR_ARRAY:
6910             updateEntries.push_back(createTemplateBinding(binding++, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6911                                                           updateRegistry.getWriteObjectOffset(offset++),
6912                                                           sizeof(samplersInfos[0])));
6913             break;
6914 
6915         default:
6916             DE_FATAL("Impossible");
6917         }
6918     }
6919 
6920     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
6921     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6922 
6923     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6924         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
6925     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6926     m_updateRegistry.push_back(updateRegistry);
6927 
6928     if (!withPush)
6929     {
6930         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
6931                                               m_updateRegistry.back().getRawPointer());
6932     }
6933 }
6934 #endif
6935 
writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)6936 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
6937 {
6938     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
6939         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
6940     const vk::VkSampler samplers[2] = {
6941         (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ?
6942             (0) :
6943             (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6944         (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ?
6945             (0) :
6946             (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
6947     };
6948     const vk::VkDescriptorImageInfo imageSamplers[2] = {
6949         makeDescriptorImageInfo(samplers[0],
6950                                 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
6951                                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6952         makeDescriptorImageInfo(samplers[1],
6953                                 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
6954                                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6955     };
6956     uint32_t binding        = 0u;
6957     uint32_t numDescriptors = 0u;
6958 
6959     // result
6960     if (setNdx == 0)
6961     {
6962         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6963                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
6964         numDescriptors++;
6965     }
6966 
6967     // combined image samplers
6968     switch (m_shaderInterface)
6969     {
6970     case SHADER_INPUT_SINGLE_DESCRIPTOR:
6971         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6972                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6973         numDescriptors++;
6974         break;
6975 
6976     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6977         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6978                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6979         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
6980                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6981         numDescriptors += 2;
6982         break;
6983 
6984     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6985         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
6986                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6987         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2u),
6988                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6989         numDescriptors += 2;
6990         break;
6991 
6992     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6993         m_updateBuilder.writeSingle(descriptorSet,
6994                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6995                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6996         m_updateBuilder.writeSingle(descriptorSet,
6997                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6998                                     vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6999         numDescriptors += 2;
7000         break;
7001 
7002     case SHADER_INPUT_DESCRIPTOR_ARRAY:
7003         m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
7004                                    vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
7005         numDescriptors++;
7006         break;
7007 
7008     default:
7009         DE_FATAL("Impossible");
7010     }
7011 
7012     m_descriptorsPerSet.push_back(numDescriptors);
7013 
7014     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
7015     {
7016         m_updateBuilder.update(m_vki, m_device);
7017         m_updateBuilder.clear();
7018     }
7019 }
7020 
7021 #ifndef CTS_USES_VULKANSC
writeImageSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)7022 void ImageSampleComputeInstance::writeImageSamplerDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
7023                                                                             vk::VkDescriptorSetLayout layout,
7024                                                                             uint32_t setNdx, bool withPush,
7025                                                                             vk::VkPipelineLayout pipelineLayout)
7026 {
7027     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
7028     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
7029         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
7030     const vk::VkSampler samplers[2] = {
7031         (m_isImmutableSampler && !withPush) ?
7032             (0) :
7033             (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
7034         (m_isImmutableSampler && !withPush) ?
7035             (0) :
7036             (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)),
7037     };
7038     const vk::VkDescriptorImageInfo imageSamplers[2] = {
7039         makeDescriptorImageInfo(samplers[0],
7040                                 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
7041                                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
7042         makeDescriptorImageInfo(samplers[1],
7043                                 m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
7044                                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
7045     };
7046     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
7047         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
7048         DE_NULL,
7049         0,
7050         0,       // updateCount
7051         DE_NULL, // pUpdates
7052         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
7053                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
7054         layout,
7055         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
7056         pipelineLayout,
7057         getDescriptorSetNdx(m_descriptorSetCount, setNdx)};
7058 
7059     uint32_t binding = 0u;
7060     uint32_t offset  = 0u;
7061     RawUpdateRegistry updateRegistry;
7062 
7063     if (setNdx == 0)
7064         updateRegistry.addWriteObject(resultInfo);
7065 
7066     updateRegistry.addWriteObject(imageSamplers[0]);
7067     updateRegistry.addWriteObject(imageSamplers[1]);
7068 
7069     // result
7070     if (setNdx == 0)
7071         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
7072                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7073 
7074     // combined image samplers
7075     switch (m_shaderInterface)
7076     {
7077     case SHADER_INPUT_SINGLE_DESCRIPTOR:
7078         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7079                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7080         break;
7081 
7082     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
7083         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7084                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7085         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7086                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7087         break;
7088 
7089     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
7090         updateEntries.push_back(createTemplateBinding(binding, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7091                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7092         updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7093                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7094         break;
7095 
7096     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
7097         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
7098                                                       vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7099                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7100         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
7101                                                       vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7102                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
7103         break;
7104 
7105     case SHADER_INPUT_DESCRIPTOR_ARRAY:
7106         updateEntries.push_back(createTemplateBinding(binding++, 0, 2, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
7107                                                       updateRegistry.getWriteObjectOffset(offset++),
7108                                                       sizeof(imageSamplers[0])));
7109         break;
7110 
7111     default:
7112         DE_FATAL("Impossible");
7113     }
7114 
7115     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
7116     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
7117 
7118     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
7119         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
7120     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
7121     m_updateRegistry.push_back(updateRegistry);
7122 
7123     if (!withPush)
7124     {
7125         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
7126                                               m_updateRegistry.back().getRawPointer());
7127     }
7128 }
7129 #endif
7130 
iterate(void)7131 tcu::TestStatus ImageSampleComputeInstance::iterate(void)
7132 {
7133     logTestPlan();
7134     return testResourceAccess();
7135 }
7136 
logTestPlan(void) const7137 void ImageSampleComputeInstance::logTestPlan(void) const
7138 {
7139     std::ostringstream msg;
7140 
7141     msg << "Accessing resource in a compute program.\n";
7142 
7143     if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
7144     {
7145         msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
7146                                                                         "Multiple descriptor sets. ")
7147             << "Each descriptor set contains "
7148             << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
7149                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
7150                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
7151                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
7152                 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
7153                                                                                          (const char *)DE_NULL)
7154             << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
7155     }
7156     else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
7157     {
7158         msg << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
7159                                                                         "Multiple descriptor sets. ")
7160             << "Each descriptor set contains "
7161             << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
7162                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
7163                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
7164                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
7165                 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
7166                                                                                          (const char *)DE_NULL)
7167             << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
7168     }
7169     else
7170         DE_FATAL("Impossible");
7171 
7172     msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
7173 
7174     if (m_baseMipLevel)
7175         msg << "Image view base mip level = " << m_baseMipLevel << "\n";
7176     if (m_baseArraySlice)
7177         msg << "Image view base array slice = " << m_baseArraySlice << "\n";
7178 
7179     if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
7180         msg << "Sampler mode is LINEAR, with WRAP\n";
7181     else
7182         msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
7183 
7184     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
7185     {
7186         msg << "Test sample " << resultNdx << ": sample at position "
7187             << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
7188 
7189         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
7190         {
7191             const int srcResourceNdx = (resultNdx % 2); // ABAB source
7192 
7193             if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
7194                 msg << " using sampler " << srcResourceNdx;
7195             else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
7196                 msg << " from combined image sampler " << srcResourceNdx;
7197             else
7198                 DE_FATAL("Impossible");
7199         }
7200         msg << "\n";
7201     }
7202 
7203     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
7204 }
7205 
testResourceAccess(void)7206 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess(void)
7207 {
7208     const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
7209     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
7210     std::vector<DescriptorSetHandleSp> descriptorSets;
7211     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
7212     std::vector<vk::VkDescriptorSet> setHandles;
7213 
7214     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7215     {
7216         vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
7217         vk::Move<vk::VkDescriptorSet> set          = createDescriptorSet(*descriptorPool, *layout, setNdx);
7218 
7219         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
7220         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
7221 
7222         layoutHandles.push_back(**descriptorSetLayouts.back());
7223         setHandles.push_back(**descriptorSets.back());
7224 
7225         // Add an empty descriptor set layout between sets 0 and 2
7226         if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
7227         {
7228             vk::DescriptorSetLayoutBuilder emptyBuilder;
7229             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
7230                 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
7231 
7232             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
7233             layoutHandles.push_back(**descriptorSetLayouts.back());
7234         }
7235     }
7236 
7237     const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
7238                                    &layoutHandles.front());
7239     const uint32_t *const dynamicOffsets                = DE_NULL;
7240     const int numDynamicOffsets                         = 0;
7241     const vk::VkBufferMemoryBarrier *const preBarriers  = DE_NULL;
7242     const int numPreBarriers                            = 0;
7243     const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
7244     const int numPostBarriers                           = 1;
7245 
7246     const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
7247                                  tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
7248                                  numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
7249                                  postBarriers, m_bind2);
7250 
7251     tcu::Vec4 results[4];
7252     bool anyResultSet = false;
7253     bool allResultsOk = true;
7254 
7255 #ifndef CTS_USES_VULKANSC
7256     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
7257     {
7258         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7259             writeDescriptorSet(DE_NULL, layoutHandles[getDescriptorSetNdx(m_descriptorSetCount, setNdx)], setNdx,
7260                                pipeline.getPipelineLayout()); // descriptor set not applicable
7261 
7262         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
7263     }
7264     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
7265     {
7266         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7267             writeDescriptorSet(DE_NULL, layoutHandles[getDescriptorSetNdx(m_descriptorSetCount, setNdx)], setNdx,
7268                                pipeline.getPipelineLayout()); // descriptor set not applicable
7269 
7270         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
7271     }
7272     else
7273 #endif
7274     {
7275         compute.submitAndWait(m_queueFamilyIndex, m_queue);
7276     }
7277     m_result.readResultContentsTo(&results);
7278 
7279     // verify
7280     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
7281     {
7282         // source image is high-frequency so the threshold is quite large to tolerate sampling errors
7283         const tcu::Vec4 samplingThreshold = tcu::Vec4(8.0f / 255.0f);
7284         const tcu::Vec4 result            = results[resultNdx];
7285         tcu::Vec4 reference               = tcu::Vec4(0.0f);
7286 
7287         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
7288             reference += m_images.fetchSampleValue(resultNdx, setNdx);
7289 
7290         reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
7291 
7292         if (result != tcu::Vec4(-1.0f))
7293             anyResultSet = true;
7294 
7295         if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
7296         {
7297             allResultsOk = false;
7298 
7299             m_context.getTestContext().getLog()
7300                 << tcu::TestLog::Message << "Test sample " << resultNdx << ":\n"
7301                 << "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx)
7302                 << "\n"
7303                 << "\tError expected " << reference << ", got " << result << tcu::TestLog::EndMessage;
7304         }
7305     }
7306 
7307     // read back and verify
7308     if (allResultsOk)
7309         return tcu::TestStatus::pass("Pass");
7310     else if (anyResultSet)
7311         return tcu::TestStatus::fail("Invalid result values");
7312     else
7313     {
7314         m_context.getTestContext().getLog()
7315             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
7316         return tcu::TestStatus::fail("Result buffer was not written to");
7317     }
7318 }
7319 
7320 class ImageDescriptorCase : public QuadrantRendederCase
7321 {
7322 public:
7323     enum
7324     {
7325         FLAG_BASE_MIP   = (1u << 1u),
7326         FLAG_BASE_SLICE = (1u << 2u),
7327     };
7328     // enum continues where resource flags ends
7329     DE_STATIC_ASSERT((uint32_t)FLAG_BASE_MIP == (uint32_t)RESOURCE_FLAG_LAST);
7330 
7331     ImageDescriptorCase(tcu::TestContext &testCtx, const char *name, bool isPrimaryCmdBuf,
7332                         DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
7333                         vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
7334                         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
7335                         vk::VkImageViewType viewType, uint32_t flags, const bool bind2);
7336 
7337     void checkSupport(Context &context) const;
7338 
7339 private:
7340     std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
7341     std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
7342     std::string genFetchCoordStr(int fetchPosNdx) const;
7343     std::string genSampleCoordStr(int samplePosNdx) const;
7344     std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
7345     std::string genNoAccessSource(void) const;
7346 
7347     vkt::TestInstance *createInstance(vkt::Context &context) const;
7348 
7349 private:
7350     const bool m_isPrimaryCmdBuf;
7351     const DescriptorUpdateMethod m_updateMethod;
7352     const vk::VkDescriptorType m_descriptorType;
7353     const DescriptorSetCount m_descriptorSetCount;
7354     const ShaderInputInterface m_shaderInterface;
7355     const vk::VkImageViewType m_viewType;
7356     const uint32_t m_baseMipLevel;
7357     const uint32_t m_baseArraySlice;
7358     const bool m_isImmutableSampler;
7359     const bool m_bind2;
7360 };
7361 
ImageDescriptorCase(tcu::TestContext & testCtx,const char * name,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t flags,const bool bind2)7362 ImageDescriptorCase::ImageDescriptorCase(tcu::TestContext &testCtx, const char *name, bool isPrimaryCmdBuf,
7363                                          DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
7364                                          vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
7365                                          DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
7366                                          vk::VkImageViewType viewType, uint32_t flags, const bool bind2)
7367     : QuadrantRendederCase(testCtx, name,
7368                            // \note 1D textures are not supported in ES
7369                            (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
7370                                glu::GLSL_VERSION_440 :
7371                                glu::GLSL_VERSION_310_ES,
7372                            exitingStages, activeStages, descriptorSetCount)
7373     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
7374     , m_updateMethod(updateMethod)
7375     , m_descriptorType(descriptorType)
7376     , m_descriptorSetCount(descriptorSetCount)
7377     , m_shaderInterface(shaderInterface)
7378     , m_viewType(viewType)
7379     , m_baseMipLevel(((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
7380     , m_baseArraySlice(((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
7381     , m_isImmutableSampler((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
7382     , m_bind2(bind2)
7383 {
7384 }
7385 
checkSupport(Context & context) const7386 void ImageDescriptorCase::checkSupport(Context &context) const
7387 {
7388     if (m_baseMipLevel == 1u)
7389     {
7390         vk::VkImageFormatProperties properties;
7391         const auto &vki                = context.getInstanceInterface();
7392         const auto physicalDevice      = context.getPhysicalDevice();
7393         const vk::VkFormat format      = vk::VK_FORMAT_R8G8B8A8_UNORM;
7394         const vk::VkImageType type     = viewTypeToImageType(m_viewType);
7395         const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
7396         const bool isStorage           = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
7397         const uint32_t readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
7398         const auto usage         = readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
7399 
7400         if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, 0, &properties) ==
7401             vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
7402             TCU_THROW(NotSupportedError, "Required format not supported");
7403         if (properties.maxMipLevels < 2u)
7404             TCU_THROW(NotSupportedError, "Required mipmap count not supported");
7405     }
7406 
7407     if (m_bind2)
7408         context.requireDeviceFunctionality("VK_KHR_maintenance6");
7409 }
7410 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const7411 std::string ImageDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
7412 {
7413     DE_UNREF(stage);
7414 
7415     if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
7416         return "#extension GL_OES_texture_cube_map_array : require\n";
7417     else
7418         return "";
7419 }
7420 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const7421 std::string ImageDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const
7422 {
7423     DE_UNREF(stage);
7424 
7425     // Vulkan-style resources are arrays implicitly, OpenGL-style are not
7426     const std::string dimensionBase =
7427         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)     ? ("1D") :
7428         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)     ? ("2D") :
7429         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                      ? ("3D") :
7430         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("Cube") :
7431                                                                                                          (DE_NULL);
7432     const std::string dimensionArray =
7433         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)     ? ("1DArray") :
7434         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)     ? ("2DArray") :
7435         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                      ? ("3D") :
7436         (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray") :
7437                                                                                                          (DE_NULL);
7438     const std::string dimension = isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
7439     const uint32_t numSets      = getDescriptorSetCount(m_descriptorSetCount);
7440 
7441     std::string buf;
7442 
7443     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
7444     {
7445         // Result buffer is bound only to the first descriptor set in compute shader cases
7446         const int descBinding =
7447             numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
7448         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
7449         const uint32_t descriptorSet    = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
7450 
7451         switch (m_shaderInterface)
7452         {
7453         case SHADER_INPUT_SINGLE_DESCRIPTOR:
7454         {
7455             switch (m_descriptorType)
7456             {
7457             case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7458                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7459                        ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7460                        ";\n"
7461                        "layout(set = " +
7462                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7463                        ") uniform highp sampler u_separateSampler" + setNdxPostfix + ";\n";
7464                 break;
7465             case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7466                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7467                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + ";\n";
7468                 break;
7469             case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7470                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7471                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + ";\n";
7472                 break;
7473             case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7474                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7475                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + ";\n";
7476                 break;
7477             default:
7478                 DE_FATAL("invalid descriptor");
7479             }
7480             break;
7481         }
7482         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
7483         {
7484             switch (m_descriptorType)
7485             {
7486             case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7487                 if (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)
7488                     buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7489                            ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7490                            ";\n"
7491                            "layout(set = " +
7492                            de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7493                            ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7494                            "A;\n"
7495                            "layout(set = " +
7496                            de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7497                            ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7498                 else
7499                     buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7500                            ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7501                            "A;\n"
7502                            "layout(set = " +
7503                            de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7504                            ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7505                            ";\n"
7506                            "layout(set = " +
7507                            de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7508                            ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7509                 break;
7510             case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7511                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7512                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix +
7513                        "A;\n"
7514                        "layout(set = " +
7515                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7516                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "B;\n";
7517                 break;
7518             case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7519                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7520                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix +
7521                        "A;\n"
7522                        "layout(set = " +
7523                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7524                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "B;\n";
7525                 break;
7526             case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7527                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7528                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix +
7529                        "A;\n"
7530                        "layout(set = " +
7531                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7532                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "B;\n";
7533                 break;
7534             default:
7535                 DE_FATAL("invalid descriptor");
7536             }
7537             break;
7538         }
7539         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
7540         {
7541             switch (m_descriptorType)
7542             {
7543             case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7544                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7545                        ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7546                        "A;\n"
7547                        "layout(set = " +
7548                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7549                        ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7550                        ";\n"
7551                        "layout(set = " +
7552                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7553                        ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7554                 break;
7555             case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7556                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7557                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix +
7558                        "A;\n"
7559                        "layout(set = " +
7560                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7561                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "B;\n";
7562                 break;
7563             case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7564                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7565                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix +
7566                        "A;\n"
7567                        "layout(set = " +
7568                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7569                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "B;\n";
7570                 break;
7571             case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7572                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7573                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix +
7574                        "A;\n"
7575                        "layout(set = " +
7576                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 2) +
7577                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "B;\n";
7578                 break;
7579             default:
7580                 DE_FATAL("invalid descriptor");
7581             }
7582             break;
7583         }
7584         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
7585         {
7586             switch (m_descriptorType)
7587             {
7588             case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7589                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7590                        ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7591                        ";\n"
7592                        "layout(set = " +
7593                        de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(0)) +
7594                        ") uniform highp sampler u_separateSampler" + setNdxPostfix +
7595                        "A;\n"
7596                        "layout(set = " +
7597                        de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7598                        ") uniform highp sampler u_separateSampler" + setNdxPostfix + "B;\n";
7599                 break;
7600             case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7601                 buf += "layout(set = " + de::toString(descriptorSet) +
7602                        ", binding = " + de::toString(getArbitraryBindingIndex(0)) + ") uniform highp sampler" +
7603                        dimension + " u_combinedTextureSampler" + setNdxPostfix +
7604                        "A;\n"
7605                        "layout(set = " +
7606                        de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7607                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "B;\n";
7608                 break;
7609             case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7610                 buf += "layout(set = " + de::toString(descriptorSet) +
7611                        ", binding = " + de::toString(getArbitraryBindingIndex(0)) + ") uniform highp texture" +
7612                        dimensionBase + " u_separateTexture" + setNdxPostfix +
7613                        "A;\n"
7614                        "layout(set = " +
7615                        de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7616                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "B;\n";
7617                 break;
7618             case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7619                 buf += "layout(set = " + de::toString(descriptorSet) +
7620                        ", binding = " + de::toString(getArbitraryBindingIndex(0)) +
7621                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix +
7622                        "A;\n"
7623                        "layout(set = " +
7624                        de::toString(descriptorSet) + ", binding = " + de::toString(getArbitraryBindingIndex(1)) +
7625                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "B;\n";
7626                 break;
7627             default:
7628                 DE_FATAL("invalid descriptor");
7629             }
7630             break;
7631         }
7632         case SHADER_INPUT_DESCRIPTOR_ARRAY:
7633         {
7634             switch (m_descriptorType)
7635             {
7636             case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7637                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7638                        ") uniform highp texture" + dimension + " u_separateTexture" + setNdxPostfix +
7639                        ";\n"
7640                        "layout(set = " +
7641                        de::toString(descriptorSet) + ", binding = " + de::toString(descBinding + 1) +
7642                        ") uniform highp sampler u_separateSampler" + setNdxPostfix + "[2];\n";
7643                 break;
7644             case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7645                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7646                        ") uniform highp sampler" + dimension + " u_combinedTextureSampler" + setNdxPostfix + "[2];\n";
7647                 break;
7648             case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7649                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7650                        ") uniform highp texture" + dimensionBase + " u_separateTexture" + setNdxPostfix + "[2];\n";
7651                 break;
7652             case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7653                 buf += "layout(set = " + de::toString(descriptorSet) + ", binding = " + de::toString(descBinding) +
7654                        ", rgba8) readonly uniform highp image" + dimension + " u_image" + setNdxPostfix + "[2];\n";
7655                 break;
7656             default:
7657                 DE_FATAL("invalid descriptor");
7658             }
7659             break;
7660         }
7661         default:
7662             DE_FATAL("Impossible");
7663         }
7664     }
7665     return buf;
7666 }
7667 
genFetchCoordStr(int fetchPosNdx) const7668 std::string ImageDescriptorCase::genFetchCoordStr(int fetchPosNdx) const
7669 {
7670     DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
7671               m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
7672     const tcu::IVec3 fetchPos =
7673         ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
7674 
7675     if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
7676     {
7677         return de::toString(fetchPos.x());
7678     }
7679     else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
7680     {
7681         std::ostringstream buf;
7682         buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
7683         return buf.str();
7684     }
7685     else
7686     {
7687         std::ostringstream buf;
7688         buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
7689         return buf.str();
7690     }
7691 }
7692 
genSampleCoordStr(int samplePosNdx) const7693 std::string ImageDescriptorCase::genSampleCoordStr(int samplePosNdx) const
7694 {
7695     DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER ||
7696               m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
7697     const tcu::Vec4 fetchPos =
7698         ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
7699 
7700     if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
7701     {
7702         std::ostringstream buf;
7703         buf << "float(" << fetchPos.x() << ")";
7704         return buf.str();
7705     }
7706     else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
7707     {
7708         std::ostringstream buf;
7709         buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
7710         return buf.str();
7711     }
7712     else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
7713     {
7714         std::ostringstream buf;
7715         buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z()
7716             << "), float(" << fetchPos.w() << "))";
7717         return buf.str();
7718     }
7719     else
7720     {
7721         std::ostringstream buf;
7722         buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
7723         return buf.str();
7724     }
7725 }
7726 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const7727 std::string ImageDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
7728 {
7729     DE_UNREF(stage);
7730 
7731     const char *const dimension      = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)         ? ("1D") :
7732                                        (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)   ? ("1DArray") :
7733                                        (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)         ? ("2D") :
7734                                        (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)   ? ("2DArray") :
7735                                        (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)         ? ("3D") :
7736                                        (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)       ? ("Cube") :
7737                                        (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray") :
7738                                                                                            (DE_NULL);
7739     const char *const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? ("") :
7740                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? ("A") :
7741                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") :
7742                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? ("A") :
7743                                        (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") :
7744                                                                                               (DE_NULL);
7745     const char *const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? ("") :
7746                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? ("B") :
7747                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") :
7748                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? ("B") :
7749                                        (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") :
7750                                                                                               (DE_NULL);
7751     const uint32_t numSets           = getDescriptorSetCount(m_descriptorSetCount);
7752 
7753     std::ostringstream buf;
7754 
7755     buf << "    result_color = vec4(0.0);\n";
7756 
7757     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
7758     {
7759         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
7760 
7761         switch (m_descriptorType)
7762         {
7763         case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7764         case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7765         {
7766             const std::string coodStr[4] = {
7767                 genSampleCoordStr(0),
7768                 genSampleCoordStr(1),
7769                 genSampleCoordStr(2),
7770                 genSampleCoordStr(3),
7771             };
7772 
7773             if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
7774             {
7775                 buf << "    if (quadrant_id == 0)\n"
7776                     << "        result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7777                     << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixA << "), " << coodStr[0]
7778                     << ", 0.0);\n"
7779                     << "    else if (quadrant_id == 1)\n"
7780                     << "        result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7781                     << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixB << "), " << coodStr[1]
7782                     << ", 0.0);\n"
7783                     << "    else if (quadrant_id == 2)\n"
7784                     << "        result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7785                     << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixA << "), " << coodStr[2]
7786                     << ", 0.0);\n"
7787                     << "    else\n"
7788                     << "        result_color += textureLod(sampler" << dimension << "(u_separateTexture"
7789                     << setNdxPostfix << ", u_separateSampler" << setNdxPostfix << accessPostfixB << "), " << coodStr[3]
7790                     << ", 0.0);\n";
7791             }
7792             else
7793             {
7794                 buf << "    if (quadrant_id == 0)\n"
7795                     << "        result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixA
7796                     << ", " << coodStr[0] << ", 0.0);\n"
7797                     << "    else if (quadrant_id == 1)\n"
7798                     << "        result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixB
7799                     << ", " << coodStr[1] << ", 0.0);\n"
7800                     << "    else if (quadrant_id == 2)\n"
7801                     << "        result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixA
7802                     << ", " << coodStr[2] << ", 0.0);\n"
7803                     << "    else\n"
7804                     << "        result_color += textureLod(u_combinedTextureSampler" << setNdxPostfix << accessPostfixB
7805                     << ", " << coodStr[3] << ", 0.0);\n";
7806             }
7807             break;
7808         }
7809 
7810         case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7811         {
7812             const std::string coodStr[4] = {
7813                 genFetchCoordStr(0),
7814                 genFetchCoordStr(1),
7815                 genFetchCoordStr(2),
7816                 genFetchCoordStr(3),
7817             };
7818 
7819             buf << "    if (quadrant_id == 0)\n"
7820                 << "        result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixA << ", " << coodStr[0]
7821                 << ");\n"
7822                 << "    else if (quadrant_id == 1)\n"
7823                 << "        result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixB << ", " << coodStr[1]
7824                 << ");\n"
7825                 << "    else if (quadrant_id == 2)\n"
7826                 << "        result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixA << ", " << coodStr[2]
7827                 << ");\n"
7828                 << "    else\n"
7829                 << "        result_color += imageLoad(u_image" << setNdxPostfix << accessPostfixB << ", " << coodStr[3]
7830                 << ");\n";
7831             break;
7832         }
7833 
7834         default:
7835             DE_FATAL("invalid descriptor");
7836         }
7837     }
7838 
7839     if (getDescriptorSetCount(m_descriptorSetCount) > 1)
7840         buf << "    result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
7841 
7842     return buf.str();
7843 }
7844 
genNoAccessSource(void) const7845 std::string ImageDescriptorCase::genNoAccessSource(void) const
7846 {
7847     return "    if (quadrant_id == 1 || quadrant_id == 2)\n"
7848            "        result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
7849            "    else\n"
7850            "        result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
7851 }
7852 
createInstance(vkt::Context & context) const7853 vkt::TestInstance *ImageDescriptorCase::createInstance(vkt::Context &context) const
7854 {
7855     verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
7856                         m_updateMethod, m_descriptorType, m_activeStages, m_viewType);
7857 
7858     switch (m_descriptorType)
7859     {
7860     case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
7861     case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
7862         if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
7863         {
7864             DE_ASSERT(m_isPrimaryCmdBuf);
7865             return new ImageSampleComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
7866                                                   m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice,
7867                                                   m_isImmutableSampler, m_bind2);
7868         }
7869         else
7870             return new ImageSampleRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
7871                                                  m_descriptorSetCount, m_activeStages, m_exitingStages,
7872                                                  m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice,
7873                                                  m_isImmutableSampler, m_bind2);
7874 
7875     case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
7876     case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
7877         if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
7878         {
7879             DE_ASSERT(m_isPrimaryCmdBuf);
7880             return new ImageFetchComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
7881                                                  m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice,
7882                                                  m_bind2);
7883         }
7884         else
7885             return new ImageFetchRenderInstance(
7886                 context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType, m_descriptorSetCount, m_activeStages,
7887                 m_exitingStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_bind2);
7888 
7889     default:
7890         DE_FATAL("Impossible");
7891         return DE_NULL;
7892     }
7893 }
7894 
7895 class TexelBufferInstanceBuffers
7896 {
7897 public:
7898     TexelBufferInstanceBuffers(vkt::Context &context, const vk::DeviceInterface &vki, vk::VkDevice device,
7899                                vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
7900                                DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
7901                                bool hasViewOffset);
7902 
7903 private:
7904     static std::vector<de::ArrayBuffer<uint8_t>> createSourceBuffers(tcu::TextureFormat imageFormat,
7905                                                                      uint32_t numTexelBuffers);
7906 
7907     static std::vector<tcu::ConstPixelBufferAccess> createSourceViews(
7908         const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers, tcu::TextureFormat imageFormat,
7909         uint32_t numTexelBuffers, uint32_t viewOffset);
7910 
7911     static std::vector<BufferHandleSp> createBuffers(const vk::DeviceInterface &vki, vk::VkDevice device,
7912                                                      vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
7913                                                      const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers,
7914                                                      std::vector<AllocationSp> &bufferMemory,
7915                                                      tcu::TextureFormat imageFormat, uint32_t numTexelBuffers,
7916                                                      uint32_t viewOffset);
7917 
7918     static std::vector<BufferViewHandleSp> createBufferViews(const vk::DeviceInterface &vki, vk::VkDevice device,
7919                                                              const std::vector<BufferHandleSp> &buffers,
7920                                                              tcu::TextureFormat imageFormat, uint32_t numTexelBuffers,
7921                                                              uint32_t viewOffset);
7922 
7923     static std::vector<vk::VkBufferMemoryBarrier> createBufferBarriers(vk::VkDescriptorType descriptorType,
7924                                                                        const std::vector<BufferHandleSp> &buffers,
7925                                                                        uint32_t numTexelBuffers);
7926 
7927     static vk::Move<vk::VkBuffer> createBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
7928                                                vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
7929                                                de::MovePtr<vk::Allocation> *outAllocation);
7930 
7931     static vk::Move<vk::VkBufferView> createBufferView(const vk::DeviceInterface &vki, vk::VkDevice device,
7932                                                        const tcu::TextureFormat &textureFormat, uint32_t offset,
7933                                                        vk::VkBuffer buffer);
7934 
7935     static vk::VkBufferMemoryBarrier createBarrier(vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
7936 
7937     static void populateSourceBuffer(const tcu::PixelBufferAccess &access, uint32_t bufferNdx);
7938 
7939     static void uploadData(const vk::DeviceInterface &vki, vk::VkDevice device, const vk::Allocation &memory,
7940                            const de::ArrayBuffer<uint8_t> &data);
7941 
7942     uint32_t getViewOffset(vkt::Context &context, bool hasViewOffset, vk::VkDescriptorType descriptorType);
7943 
7944 public:
7945     static int getFetchPos(int fetchPosNdx);
7946     tcu::Vec4 fetchTexelValue(int fetchPosNdx, int setNdx) const;
7947 
getNumTexelBuffers(void) const7948     inline int getNumTexelBuffers(void) const
7949     {
7950         return m_numTexelBuffers;
7951     }
getTextureFormat(void) const7952     const tcu::TextureFormat &getTextureFormat(void) const
7953     {
7954         return m_imageFormat;
7955     }
getBufferView(int ndx) const7956     inline vk::VkBufferView getBufferView(int ndx) const
7957     {
7958         return **m_bufferView[ndx % m_bufferView.size()];
7959     }
getSourceView(int ndx) const7960     inline tcu::ConstPixelBufferAccess getSourceView(int ndx) const
7961     {
7962         return m_sourceView[ndx % m_sourceView.size()];
7963     }
getBufferInitBarriers(void) const7964     inline const vk::VkBufferMemoryBarrier *getBufferInitBarriers(void) const
7965     {
7966         return &m_bufferBarrier.front();
7967     }
7968 
7969 private:
7970     enum
7971     {
7972         BUFFER_SIZE    = 512,
7973         VIEW_DATA_SIZE = 256, //!< size in bytes
7974         VIEW_WIDTH     = 64,  //!< size in pixels
7975     };
7976     enum
7977     {
7978         // some arbitrary points
7979         SAMPLE_POINT_0 = 6,
7980         SAMPLE_POINT_1 = 51,
7981         SAMPLE_POINT_2 = 42,
7982         SAMPLE_POINT_3 = 25,
7983     };
7984 
7985     const uint32_t m_numTexelBuffers;
7986     const tcu::TextureFormat m_imageFormat;
7987     const ShaderInputInterface m_shaderInterface;
7988     const uint32_t m_viewOffset;
7989 
7990     const std::vector<de::ArrayBuffer<uint8_t>> m_sourceBuffer;
7991     const std::vector<tcu::ConstPixelBufferAccess> m_sourceView;
7992 
7993     std::vector<AllocationSp> m_bufferMemory;
7994     const std::vector<BufferHandleSp> m_buffer;
7995     const std::vector<BufferViewHandleSp> m_bufferView;
7996     const std::vector<vk::VkBufferMemoryBarrier> m_bufferBarrier;
7997 };
7998 
getViewOffset(vkt::Context & context,bool hasViewOffset,vk::VkDescriptorType descriptorType)7999 uint32_t TexelBufferInstanceBuffers::getViewOffset(vkt::Context &context, bool hasViewOffset,
8000                                                    vk::VkDescriptorType descriptorType)
8001 {
8002     if (!hasViewOffset)
8003         return 0u;
8004 
8005     if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
8006         return (uint32_t)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
8007 
8008     vk::VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
8009     deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
8010     alignmentProperties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
8011 
8012     vk::VkPhysicalDeviceProperties2 properties2;
8013     deMemset(&properties2, 0, sizeof(properties2));
8014     properties2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
8015     properties2.pNext = &alignmentProperties;
8016 
8017     context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
8018 
8019     vk::VkBool32 singleTexelAlignment = isUniformDescriptorType(descriptorType) ?
8020                                             alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
8021                                             alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
8022     vk::VkDeviceSize align            = isUniformDescriptorType(descriptorType) ?
8023                                             alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
8024                                             alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
8025 
8026     // format is rgba8
8027     if (singleTexelAlignment)
8028         return de::min(4u, (uint32_t)align);
8029     else
8030         return (uint32_t)align;
8031 }
8032 
TexelBufferInstanceBuffers(vkt::Context & context,const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool hasViewOffset)8033 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers(vkt::Context &context, const vk::DeviceInterface &vki,
8034                                                        vk::VkDevice device, vk::Allocator &allocator,
8035                                                        vk::VkDescriptorType descriptorType,
8036                                                        DescriptorSetCount descriptorSetCount,
8037                                                        ShaderInputInterface shaderInterface, bool hasViewOffset)
8038     : m_numTexelBuffers(getInterfaceNumResources(shaderInterface) * getDescriptorSetCount(descriptorSetCount))
8039     , m_imageFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
8040     , m_shaderInterface(shaderInterface)
8041     , m_viewOffset(getViewOffset(context, hasViewOffset, descriptorType))
8042     , m_sourceBuffer(createSourceBuffers(m_imageFormat, m_numTexelBuffers))
8043     , m_sourceView(createSourceViews(m_sourceBuffer, m_imageFormat, m_numTexelBuffers, m_viewOffset))
8044     , m_bufferMemory()
8045     , m_buffer(createBuffers(vki, device, allocator, descriptorType, m_sourceBuffer, m_bufferMemory, m_imageFormat,
8046                              m_numTexelBuffers, m_viewOffset))
8047     , m_bufferView(createBufferViews(vki, device, m_buffer, m_imageFormat, m_numTexelBuffers, m_viewOffset))
8048     , m_bufferBarrier(createBufferBarriers(descriptorType, m_buffer, m_numTexelBuffers))
8049 {
8050 }
8051 
createSourceBuffers(tcu::TextureFormat imageFormat,uint32_t numTexelBuffers)8052 std::vector<de::ArrayBuffer<uint8_t>> TexelBufferInstanceBuffers::createSourceBuffers(tcu::TextureFormat imageFormat,
8053                                                                                       uint32_t numTexelBuffers)
8054 {
8055     DE_ASSERT(BUFFER_SIZE % imageFormat.getPixelSize() == 0);
8056 
8057     std::vector<de::ArrayBuffer<uint8_t>> sourceBuffers(numTexelBuffers, BUFFER_SIZE);
8058 
8059     for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8060         populateSourceBuffer(tcu::PixelBufferAccess(imageFormat,
8061                                                     tcu::IVec3(BUFFER_SIZE / imageFormat.getPixelSize(), 1, 1),
8062                                                     sourceBuffers[bufferNdx].getPtr()),
8063                              bufferNdx);
8064 
8065     return sourceBuffers;
8066 }
8067 
createSourceViews(const std::vector<de::ArrayBuffer<uint8_t>> & sourceBuffers,tcu::TextureFormat imageFormat,uint32_t numTexelBuffers,uint32_t viewOffset)8068 std::vector<tcu::ConstPixelBufferAccess> TexelBufferInstanceBuffers::createSourceViews(
8069     const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers, tcu::TextureFormat imageFormat,
8070     uint32_t numTexelBuffers, uint32_t viewOffset)
8071 {
8072     std::vector<tcu::ConstPixelBufferAccess> sourceViews;
8073 
8074     for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8075         sourceViews.push_back(tcu::ConstPixelBufferAccess(imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1),
8076                                                           sourceBuffers[bufferNdx].getElementPtr(viewOffset)));
8077 
8078     return sourceViews;
8079 }
8080 
createBuffers(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,const std::vector<de::ArrayBuffer<uint8_t>> & sourceBuffers,std::vector<AllocationSp> & bufferMemory,tcu::TextureFormat imageFormat,uint32_t numTexelBuffers,uint32_t viewOffset)8081 std::vector<BufferHandleSp> TexelBufferInstanceBuffers::createBuffers(
8082     const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
8083     const std::vector<de::ArrayBuffer<uint8_t>> &sourceBuffers, std::vector<AllocationSp> &bufferMemory,
8084     tcu::TextureFormat imageFormat, uint32_t numTexelBuffers, uint32_t viewOffset)
8085 {
8086     std::vector<BufferHandleSp> buffers;
8087 
8088     for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8089     {
8090         de::MovePtr<vk::Allocation> memory;
8091         vk::Move<vk::VkBuffer> buffer         = createBuffer(vki, device, allocator, descriptorType, &memory);
8092         vk::Move<vk::VkBufferView> bufferView = createBufferView(vki, device, imageFormat, viewOffset, *buffer);
8093 
8094         uploadData(vki, device, *memory, sourceBuffers[bufferNdx]);
8095 
8096         bufferMemory.push_back(AllocationSp(memory.release()));
8097         buffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
8098     }
8099 
8100     return buffers;
8101 }
8102 
createBufferViews(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<BufferHandleSp> & buffers,tcu::TextureFormat imageFormat,uint32_t numTexelBuffers,uint32_t viewOffset)8103 std::vector<BufferViewHandleSp> TexelBufferInstanceBuffers::createBufferViews(
8104     const vk::DeviceInterface &vki, vk::VkDevice device, const std::vector<BufferHandleSp> &buffers,
8105     tcu::TextureFormat imageFormat, uint32_t numTexelBuffers, uint32_t viewOffset)
8106 {
8107     std::vector<BufferViewHandleSp> bufferViews;
8108 
8109     for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8110     {
8111         vk::Move<vk::VkBufferView> bufferView =
8112             createBufferView(vki, device, imageFormat, viewOffset, **buffers[bufferNdx]);
8113         bufferViews.push_back(BufferViewHandleSp(new BufferViewHandleUp(bufferView)));
8114     }
8115 
8116     return bufferViews;
8117 }
8118 
createBufferBarriers(vk::VkDescriptorType descriptorType,const std::vector<BufferHandleSp> & buffers,uint32_t numTexelBuffers)8119 std::vector<vk::VkBufferMemoryBarrier> TexelBufferInstanceBuffers::createBufferBarriers(
8120     vk::VkDescriptorType descriptorType, const std::vector<BufferHandleSp> &buffers, uint32_t numTexelBuffers)
8121 {
8122     std::vector<vk::VkBufferMemoryBarrier> bufferBarriers;
8123 
8124     for (uint32_t bufferNdx = 0; bufferNdx < numTexelBuffers; bufferNdx++)
8125         bufferBarriers.push_back(createBarrier(descriptorType, **buffers[bufferNdx]));
8126 
8127     return bufferBarriers;
8128 }
8129 
createBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkDescriptorType descriptorType,de::MovePtr<vk::Allocation> * outAllocation)8130 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
8131                                                                 vk::Allocator &allocator,
8132                                                                 vk::VkDescriptorType descriptorType,
8133                                                                 de::MovePtr<vk::Allocation> *outAllocation)
8134 {
8135     const vk::VkBufferUsageFlags usage      = (isUniformDescriptorType(descriptorType)) ?
8136                                                   (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) :
8137                                                   (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
8138     const vk::VkBufferCreateInfo createInfo = {
8139         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
8140         DE_NULL,
8141         0u,                            // flags
8142         (vk::VkDeviceSize)BUFFER_SIZE, // size
8143         usage,                         // usage
8144         vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
8145         0u,                            // queueFamilyCount
8146         DE_NULL,                       // pQueueFamilyIndices
8147     };
8148     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &createInfo));
8149     de::MovePtr<vk::Allocation> allocation(
8150         allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
8151 
8152     *outAllocation = allocation;
8153     return buffer;
8154 }
8155 
createBufferView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & textureFormat,uint32_t offset,vk::VkBuffer buffer)8156 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView(const vk::DeviceInterface &vki,
8157                                                                         vk::VkDevice device,
8158                                                                         const tcu::TextureFormat &textureFormat,
8159                                                                         uint32_t offset, vk::VkBuffer buffer)
8160 {
8161     const vk::VkBufferViewCreateInfo createInfo = {
8162         vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
8163         DE_NULL,
8164         (vk::VkBufferViewCreateFlags)0,
8165         buffer,                              // buffer
8166         vk::mapTextureFormat(textureFormat), // format
8167         (vk::VkDeviceSize)offset,            // offset
8168         (vk::VkDeviceSize)VIEW_DATA_SIZE     // range
8169     };
8170     return vk::createBufferView(vki, device, &createInfo);
8171 }
8172 
createBarrier(vk::VkDescriptorType descriptorType,vk::VkBuffer buffer)8173 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier(vk::VkDescriptorType descriptorType,
8174                                                                     vk::VkBuffer buffer)
8175 {
8176     const vk::VkAccessFlags inputBit =
8177         (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
8178     const vk::VkBufferMemoryBarrier barrier = {
8179         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
8180         DE_NULL,
8181         vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
8182         inputBit,                     // dstAccessMask
8183         VK_QUEUE_FAMILY_IGNORED,      // srcQueueFamilyIndex
8184         VK_QUEUE_FAMILY_IGNORED,      // destQueueFamilyIndex
8185         buffer,                       // buffer
8186         0u,                           // offset
8187         (vk::VkDeviceSize)BUFFER_SIZE // size
8188     };
8189     return barrier;
8190 }
8191 
populateSourceBuffer(const tcu::PixelBufferAccess & access,uint32_t bufferNdx)8192 void TexelBufferInstanceBuffers::populateSourceBuffer(const tcu::PixelBufferAccess &access, uint32_t bufferNdx)
8193 {
8194     DE_ASSERT(access.getHeight() == 1);
8195     DE_ASSERT(access.getDepth() == 1);
8196 
8197     const int32_t width = access.getWidth();
8198 
8199     for (int x = 0; x < width; ++x)
8200     {
8201         int red   = 255 * x / width; //!< gradient from 0 -> max (detects large offset errors)
8202         int green = ((x % 2 == 0) ? (127) : (0)) +
8203                     ((x % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
8204         int blue = 16 * (x % 16);                //!< 16-long triangle wave
8205 
8206         DE_ASSERT(de::inRange(red, 0, 255));
8207         DE_ASSERT(de::inRange(green, 0, 255));
8208         DE_ASSERT(de::inRange(blue, 0, 255));
8209 
8210         if (bufferNdx % 2 == 0)
8211             red = 255 - red;
8212         if (bufferNdx % 3 == 0)
8213             green = 255 - green;
8214         if (bufferNdx % 4 == 0)
8215             blue = 255 - blue;
8216 
8217         access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
8218     }
8219 }
8220 
uploadData(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::Allocation & memory,const de::ArrayBuffer<uint8_t> & data)8221 void TexelBufferInstanceBuffers::uploadData(const vk::DeviceInterface &vki, vk::VkDevice device,
8222                                             const vk::Allocation &memory, const de::ArrayBuffer<uint8_t> &data)
8223 {
8224     deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
8225     flushAlloc(vki, device, memory);
8226 }
8227 
getFetchPos(int fetchPosNdx)8228 int TexelBufferInstanceBuffers::getFetchPos(int fetchPosNdx)
8229 {
8230     static const int fetchPositions[4] = {
8231         SAMPLE_POINT_0,
8232         SAMPLE_POINT_1,
8233         SAMPLE_POINT_2,
8234         SAMPLE_POINT_3,
8235     };
8236     return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
8237 }
8238 
fetchTexelValue(int fetchPosNdx,int setNdx) const8239 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue(int fetchPosNdx, int setNdx) const
8240 {
8241     // source order is ABAB
8242     const tcu::ConstPixelBufferAccess &texelSrcA = getSourceView(setNdx * getInterfaceNumResources(m_shaderInterface));
8243     const tcu::ConstPixelBufferAccess &texelSrcB =
8244         getSourceView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
8245     const tcu::ConstPixelBufferAccess &texelSrc = ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
8246 
8247     return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
8248 }
8249 
8250 class TexelBufferRenderInstance : public SingleCmdRenderInstance
8251 {
8252 public:
8253     TexelBufferRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
8254                               vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
8255                               vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
8256                               ShaderInputInterface shaderInterface, bool nonzeroViewOffset, const bool bind2);
8257 
8258 private:
8259     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
8260         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8261         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
8262         DescriptorUpdateMethod updateMethod);
8263 
8264     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
8265         const vk::DeviceInterface &vki, vk::VkDevice device,
8266         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
8267 
8268     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
8269                                                                vk::VkDescriptorType descriptorType,
8270                                                                DescriptorSetCount descriptorSetCount,
8271                                                                ShaderInputInterface shaderInterface);
8272 
8273     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
8274         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
8275         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
8276         ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
8277         vk::VkDescriptorPool pool, const TexelBufferInstanceBuffers &buffers,
8278         vk::DescriptorSetUpdateBuilder &updateBuilder,
8279 #ifndef CTS_USES_VULKANSC
8280         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
8281 #endif
8282         std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = DE_NULL);
8283 
8284     static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
8285                                    vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
8286                                    vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool, vk::VkBufferView viewA,
8287                                    vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8288                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
8289                                    std::vector<uint32_t> &descriptorsPerSet,
8290                                    DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
8291 
8292 #ifndef CTS_USES_VULKANSC
8293     static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
8294                                                vk::VkDescriptorType descriptorType,
8295                                                ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout,
8296                                                uint32_t setNdx, vk::VkDescriptorPool pool, vk::VkBufferView viewA,
8297                                                vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8298                                                std::vector<UpdateTemplateHandleSp> &updateTemplates,
8299                                                std::vector<RawUpdateRegistry> &registry, bool withPush = false,
8300                                                vk::VkPipelineLayout pipelineLayout = 0);
8301 #endif
8302 
8303     void logTestPlan(void) const;
8304     vk::VkPipelineLayout getPipelineLayout(void) const;
8305     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
8306     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
8307 
8308     enum
8309     {
8310         RENDER_SIZE = 128,
8311     };
8312 
8313     const DescriptorUpdateMethod m_updateMethod;
8314     const vk::VkDescriptorType m_descriptorType;
8315     const DescriptorSetCount m_descriptorSetCount;
8316     const vk::VkShaderStageFlags m_stageFlags;
8317     const vk::VkShaderStageFlags m_existingStages;
8318     const ShaderInputInterface m_shaderInterface;
8319     const bool m_nonzeroViewOffset;
8320 
8321 #ifndef CTS_USES_VULKANSC
8322     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
8323     std::vector<RawUpdateRegistry> m_updateRegistry;
8324 #endif
8325     vk::DescriptorSetUpdateBuilder m_updateBuilder;
8326     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
8327     const vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
8328     const TexelBufferInstanceBuffers m_texelBuffers;
8329     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
8330     std::vector<uint32_t> m_descriptorsPerSet;
8331     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
8332 };
8333 
TexelBufferRenderInstance(vkt::Context & context,DescriptorUpdateMethod updateMethod,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,vk::VkShaderStageFlags stageFlags,vk::VkShaderStageFlags existingStages,ShaderInputInterface shaderInterface,bool nonzeroViewOffset,const bool bind2)8334 TexelBufferRenderInstance::TexelBufferRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
8335                                                      bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
8336                                                      DescriptorSetCount descriptorSetCount,
8337                                                      vk::VkShaderStageFlags stageFlags,
8338                                                      vk::VkShaderStageFlags existingStages,
8339                                                      ShaderInputInterface shaderInterface, bool nonzeroViewOffset,
8340                                                      const bool bind2)
8341     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
8342     , m_updateMethod(updateMethod)
8343     , m_descriptorType(descriptorType)
8344     , m_descriptorSetCount(descriptorSetCount)
8345     , m_stageFlags(stageFlags)
8346     , m_existingStages(existingStages)
8347     , m_shaderInterface(shaderInterface)
8348     , m_nonzeroViewOffset(nonzeroViewOffset)
8349 #ifndef CTS_USES_VULKANSC
8350     , m_updateTemplates()
8351     , m_updateRegistry()
8352 #endif
8353     , m_updateBuilder()
8354     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
8355                                                         m_shaderInterface, m_stageFlags, m_updateMethod))
8356     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
8357     , m_texelBuffers(context, m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount, m_shaderInterface,
8358                      m_nonzeroViewOffset)
8359     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
8360     , m_descriptorsPerSet()
8361     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
8362                                             m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool,
8363                                             m_texelBuffers, m_updateBuilder,
8364 #ifndef CTS_USES_VULKANSC
8365                                             m_updateTemplates, m_updateRegistry,
8366 #endif
8367                                             m_descriptorsPerSet, *m_pipelineLayout))
8368 {
8369 }
8370 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)8371 std::vector<DescriptorSetLayoutHandleSp> TexelBufferRenderInstance::createDescriptorSetLayouts(
8372     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8373     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
8374     DescriptorUpdateMethod updateMethod)
8375 {
8376 #ifdef CTS_USES_VULKANSC
8377     DE_UNREF(updateMethod);
8378 #endif
8379     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
8380 
8381     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
8382     {
8383         vk::DescriptorSetLayoutBuilder builder;
8384         vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
8385 
8386 #ifndef CTS_USES_VULKANSC
8387         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
8388             updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8389         {
8390             extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
8391         }
8392 #endif
8393 
8394         switch (shaderInterface)
8395         {
8396         case SHADER_INPUT_SINGLE_DESCRIPTOR:
8397             builder.addSingleBinding(descriptorType, stageFlags);
8398             break;
8399 
8400         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8401             builder.addSingleBinding(descriptorType, stageFlags);
8402             builder.addSingleBinding(descriptorType, stageFlags);
8403             break;
8404 
8405         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8406             builder.addSingleIndexedBinding(descriptorType, stageFlags, 0);
8407             builder.addSingleIndexedBinding(descriptorType, stageFlags, 2);
8408             break;
8409 
8410         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8411             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
8412             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
8413             break;
8414 
8415         case SHADER_INPUT_DESCRIPTOR_ARRAY:
8416             builder.addArrayBinding(descriptorType, 2u, stageFlags);
8417             break;
8418 
8419         default:
8420             DE_FATAL("Impossible");
8421         }
8422 
8423         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
8424         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
8425 
8426         // Add an empty descriptor set layout between sets 0 and 2
8427         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
8428         {
8429             vk::DescriptorSetLayoutBuilder emptyBuilder;
8430             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
8431                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
8432             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
8433         }
8434     }
8435     return descriptorSetLayouts;
8436 }
8437 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)8438 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout(
8439     const vk::DeviceInterface &vki, vk::VkDevice device,
8440     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
8441 {
8442     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
8443     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
8444         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
8445 
8446     const vk::VkPipelineLayoutCreateInfo createInfo = {
8447         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
8448         DE_NULL,
8449         (vk::VkPipelineLayoutCreateFlags)0,
8450         (uint32_t)layoutHandles.size(), // descriptorSetCount
8451         &layoutHandles.front(),         // pSetLayouts
8452         0u,                             // pushConstantRangeCount
8453         DE_NULL,                        // pPushConstantRanges
8454     };
8455     return vk::createPipelineLayout(vki, device, &createInfo);
8456 }
8457 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)8458 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
8459                                                                                vk::VkDevice device,
8460                                                                                vk::VkDescriptorType descriptorType,
8461                                                                                DescriptorSetCount descriptorSetCount,
8462                                                                                ShaderInputInterface shaderInterface)
8463 {
8464     return vk::DescriptorPoolBuilder()
8465         .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
8466         .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
8467                getDescriptorSetCount(descriptorSetCount));
8468 }
8469 
createDescriptorSets(const vk::DeviceInterface & vki,DescriptorUpdateMethod updateMethod,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayouts,vk::VkDescriptorPool pool,const TexelBufferInstanceBuffers & buffers,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & updateRegistry,std::vector<uint32_t> & descriptorsPerSet,vk::VkPipelineLayout pipelineLayout)8470 std::vector<DescriptorSetHandleSp> TexelBufferRenderInstance::createDescriptorSets(
8471     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
8472     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
8473     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool,
8474     const TexelBufferInstanceBuffers &buffers, vk::DescriptorSetUpdateBuilder &updateBuilder,
8475 #ifndef CTS_USES_VULKANSC
8476     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
8477 #endif
8478     std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
8479 {
8480 #ifdef CTS_USES_VULKANSC
8481     DE_UNREF(pipelineLayout);
8482 #endif
8483     std::vector<DescriptorSetHandleSp> descriptorSets;
8484 
8485     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
8486     {
8487         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
8488 
8489         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
8490                                                            pool, 1u, &layout};
8491 
8492         vk::VkBufferView viewA = buffers.getBufferView(setNdx * getInterfaceNumResources(shaderInterface));
8493         vk::VkBufferView viewB = buffers.getBufferView(setNdx * getInterfaceNumResources(shaderInterface) + 1);
8494 
8495         vk::Move<vk::VkDescriptorSet> descriptorSet;
8496 
8497         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
8498             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
8499         {
8500             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
8501         }
8502         else
8503         {
8504             descriptorSet = vk::Move<vk::VkDescriptorSet>();
8505         }
8506 
8507 #ifndef CTS_USES_VULKANSC
8508         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
8509         {
8510             writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, setNdx, pool, viewA,
8511                                            viewB, *descriptorSet, updateTemplates, updateRegistry);
8512         }
8513         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
8514         {
8515             writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, setNdx, pool, viewA,
8516                                            viewB, *descriptorSet, updateTemplates, updateRegistry, true,
8517                                            pipelineLayout);
8518         }
8519         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8520         {
8521             writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
8522                                updateBuilder, descriptorsPerSet, updateMethod);
8523         }
8524         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
8525 #endif
8526         {
8527             writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
8528                                updateBuilder, descriptorsPerSet);
8529         }
8530 
8531         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
8532     }
8533 
8534     return descriptorSets;
8535 }
8536 
writeDescriptorSet(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,vk::VkDescriptorPool pool,vk::VkBufferView viewA,vk::VkBufferView viewB,vk::VkDescriptorSet descriptorSet,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet,DescriptorUpdateMethod updateMethod)8537 void TexelBufferRenderInstance::writeDescriptorSet(
8538     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8539     ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
8540     vk::VkBufferView viewA, vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8541     vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
8542     DescriptorUpdateMethod updateMethod)
8543 {
8544     DE_UNREF(layout);
8545     DE_UNREF(pool);
8546     const vk::VkBufferView texelBufferInfos[2] = {
8547         viewA,
8548         viewB,
8549     };
8550     uint32_t numDescriptors = 0u;
8551 
8552     switch (shaderInterface)
8553     {
8554     case SHADER_INPUT_SINGLE_DESCRIPTOR:
8555         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8556                                   &texelBufferInfos[0]);
8557         numDescriptors++;
8558         break;
8559 
8560     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8561         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8562                                   &texelBufferInfos[0]);
8563         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
8564                                   &texelBufferInfos[1]);
8565         numDescriptors += 2;
8566         break;
8567 
8568     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8569         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8570                                   &texelBufferInfos[0]);
8571         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
8572                                   &texelBufferInfos[1]);
8573         numDescriptors += 2;
8574         break;
8575 
8576     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8577         updateBuilder.writeSingle(descriptorSet,
8578                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
8579                                   descriptorType, &texelBufferInfos[0]);
8580         updateBuilder.writeSingle(descriptorSet,
8581                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
8582                                   descriptorType, &texelBufferInfos[1]);
8583         numDescriptors += 2;
8584         break;
8585 
8586     case SHADER_INPUT_DESCRIPTOR_ARRAY:
8587         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
8588                                  2u, texelBufferInfos);
8589         numDescriptors++;
8590         break;
8591 
8592     default:
8593         DE_FATAL("Impossible");
8594     }
8595 
8596     descriptorsPerSet.push_back(numDescriptors);
8597 
8598     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
8599     {
8600         updateBuilder.update(vki, device);
8601         updateBuilder.clear();
8602     }
8603 }
8604 
8605 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,ShaderInputInterface shaderInterface,vk::VkDescriptorSetLayout layout,uint32_t setNdx,vk::VkDescriptorPool pool,vk::VkBufferView viewA,vk::VkBufferView viewB,vk::VkDescriptorSet descriptorSet,std::vector<UpdateTemplateHandleSp> & updateTemplates,std::vector<RawUpdateRegistry> & registry,bool withPush,vk::VkPipelineLayout pipelineLayout)8606 void TexelBufferRenderInstance::writeDescriptorSetWithTemplate(
8607     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
8608     ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, uint32_t setNdx, vk::VkDescriptorPool pool,
8609     vk::VkBufferView viewA, vk::VkBufferView viewB, vk::VkDescriptorSet descriptorSet,
8610     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
8611     vk::VkPipelineLayout pipelineLayout)
8612 {
8613     DE_UNREF(pool);
8614     const vk::VkBufferView texelBufferInfos[2] = {
8615         viewA,
8616         viewB,
8617     };
8618     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
8619     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
8620         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
8621         DE_NULL,
8622         0,
8623         0,       // updateCount
8624         DE_NULL, // pUpdates
8625         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
8626                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
8627         layout,
8628         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
8629         pipelineLayout,
8630         setNdx};
8631 
8632     RawUpdateRegistry updateRegistry;
8633 
8634     updateRegistry.addWriteObject(texelBufferInfos[0]);
8635     updateRegistry.addWriteObject(texelBufferInfos[1]);
8636 
8637     switch (shaderInterface)
8638     {
8639     case SHADER_INPUT_SINGLE_DESCRIPTOR:
8640         updateEntries.push_back(
8641             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
8642         break;
8643 
8644     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8645         updateEntries.push_back(
8646             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
8647         updateEntries.push_back(
8648             createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
8649         break;
8650 
8651     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8652         updateEntries.push_back(
8653             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
8654         updateEntries.push_back(
8655             createTemplateBinding(2, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
8656         break;
8657 
8658     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8659         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
8660                                                       updateRegistry.getWriteObjectOffset(0), 0));
8661         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
8662                                                       updateRegistry.getWriteObjectOffset(1), 0));
8663         break;
8664 
8665     case SHADER_INPUT_DESCRIPTOR_ARRAY:
8666         updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
8667                                                       sizeof(texelBufferInfos[0])));
8668         break;
8669 
8670     default:
8671         DE_FATAL("Impossible");
8672     }
8673 
8674     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
8675     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
8676 
8677     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
8678         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
8679     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
8680     registry.push_back(updateRegistry);
8681 
8682     if (!withPush)
8683     {
8684         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
8685                                             registry.back().getRawPointer());
8686     }
8687 }
8688 #endif
8689 
logTestPlan(void) const8690 void TexelBufferRenderInstance::logTestPlan(void) const
8691 {
8692     std::ostringstream msg;
8693 
8694     msg << "Rendering 2x2 grid.\n"
8695         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
8696                                                                     "Multiple descriptor sets. ")
8697         << "Each descriptor set contains "
8698         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
8699             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
8700             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
8701             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
8702             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
8703                                                                                      (const char *)DE_NULL)
8704         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
8705         << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
8706         << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
8707 
8708     if (m_stageFlags == 0u)
8709     {
8710         msg << "Descriptors are not accessed in any shader stage.\n";
8711     }
8712     else
8713     {
8714         msg << "Color in each cell is fetched using the descriptor(s):\n";
8715 
8716         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
8717         {
8718             msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
8719 
8720             if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
8721             {
8722                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
8723                 msg << " from texelBuffer " << srcResourceNdx;
8724             }
8725 
8726             msg << "\n";
8727         }
8728 
8729         msg << "Descriptors are accessed in {"
8730             << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
8731             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
8732             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
8733             << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
8734             << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
8735     }
8736 
8737     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
8738 }
8739 
getPipelineLayout(void) const8740 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout(void) const
8741 {
8742     return *m_pipelineLayout;
8743 }
8744 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const8745 void TexelBufferRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
8746 {
8747     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
8748         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8749     {
8750         std::vector<vk::VkDescriptorSet> sets;
8751         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8752             sets.push_back(**m_descriptorSets[setNdx]);
8753 
8754         switch (m_descriptorSetCount)
8755         {
8756         case DESCRIPTOR_SET_COUNT_SINGLE:
8757         case DESCRIPTOR_SET_COUNT_MULTIPLE:
8758         {
8759             bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
8760                                getPipelineLayout(), 0, (uint32_t)sets.size(), &sets.front(), 0, DE_NULL, m_bind2);
8761             break;
8762         }
8763         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
8764         {
8765             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8766             {
8767                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
8768                 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
8769                                    getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], 0, DE_NULL, m_bind2);
8770             }
8771             break;
8772         }
8773         default:
8774             DE_FATAL("Impossible");
8775         }
8776     }
8777 #ifndef CTS_USES_VULKANSC
8778     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
8779     {
8780         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8781         {
8782             const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
8783             m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
8784                                                       descriptorSetNdx,
8785                                                       (const void *)m_updateRegistry[setNdx].getRawPointer());
8786         }
8787     }
8788     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8789     {
8790         uint32_t descriptorNdx = 0u;
8791         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
8792         {
8793             const uint32_t numDescriptors   = m_descriptorsPerSet[setNdx];
8794             const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
8795             m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
8796                                            descriptorSetNdx, descriptorNdx, numDescriptors);
8797             descriptorNdx += numDescriptors;
8798         }
8799     }
8800 #endif
8801 
8802     m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
8803 }
8804 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const8805 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
8806 {
8807     const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
8808     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
8809     const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
8810     const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
8811 
8812     tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
8813 
8814     tcu::Vec4 sample0 = tcu::Vec4(0.0f);
8815     tcu::Vec4 sample1 = tcu::Vec4(0.0f);
8816     tcu::Vec4 sample2 = tcu::Vec4(0.0f);
8817     tcu::Vec4 sample3 = tcu::Vec4(0.0f);
8818 
8819     if (doFetch)
8820     {
8821         for (uint32_t setNdx = 0u; setNdx < numDescriptorSets; setNdx++)
8822         {
8823             sample0 += m_texelBuffers.fetchTexelValue(0, setNdx);
8824             sample1 += m_texelBuffers.fetchTexelValue(1, setNdx);
8825             sample2 += m_texelBuffers.fetchTexelValue(2, setNdx);
8826             sample3 += m_texelBuffers.fetchTexelValue(3, setNdx);
8827         }
8828 
8829         if (numDescriptorSets > 1)
8830         {
8831             sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
8832             sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
8833             sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
8834             sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
8835         }
8836     }
8837     else
8838     {
8839         sample0 = yellow;
8840         sample1 = green;
8841         sample2 = green;
8842         sample3 = yellow;
8843     }
8844 
8845     drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
8846 
8847     if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
8848                          result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
8849         return tcu::TestStatus::fail("Image verification failed");
8850     else
8851         return tcu::TestStatus::pass("Pass");
8852 }
8853 
8854 class TexelBufferComputeInstance : public vkt::TestInstance
8855 {
8856 public:
8857     TexelBufferComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
8858                                vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
8859                                ShaderInputInterface shaderInterface, bool nonzeroViewOffset, const bool bind2);
8860 
8861 private:
8862     vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
8863     vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
8864     vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
8865                                                       uint32_t setNdx);
8866     void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
8867 #ifndef CTS_USES_VULKANSC
8868     void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
8869                                         uint32_t setNdx, bool withPush = false,
8870                                         vk::VkPipelineLayout pipelineLayout = DE_NULL);
8871 #endif
8872 
8873     tcu::TestStatus iterate(void);
8874     void logTestPlan(void) const;
8875     tcu::TestStatus testResourceAccess(void);
8876 
8877     const DescriptorUpdateMethod m_updateMethod;
8878     const vk::VkDescriptorType m_descriptorType;
8879     const DescriptorSetCount m_descriptorSetCount;
8880     const ShaderInputInterface m_shaderInterface;
8881     const bool m_nonzeroViewOffset;
8882     const bool m_bind2;
8883 
8884     const vk::DeviceInterface &m_vki;
8885     const vk::VkDevice m_device;
8886     const vk::VkQueue m_queue;
8887     const uint32_t m_queueFamilyIndex;
8888     vk::Allocator &m_allocator;
8889 #ifndef CTS_USES_VULKANSC
8890     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
8891 #endif
8892 
8893     const ComputeInstanceResultBuffer m_result;
8894     const TexelBufferInstanceBuffers m_texelBuffers;
8895 
8896 #ifndef CTS_USES_VULKANSC
8897     std::vector<RawUpdateRegistry> m_updateRegistry;
8898 #endif
8899     vk::DescriptorSetUpdateBuilder m_updateBuilder;
8900     std::vector<uint32_t> m_descriptorsPerSet;
8901 };
8902 
TexelBufferComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool nonzeroViewOffset,const bool bind2)8903 TexelBufferComputeInstance::TexelBufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
8904                                                        vk::VkDescriptorType descriptorType,
8905                                                        DescriptorSetCount descriptorSetCount,
8906                                                        ShaderInputInterface shaderInterface, bool nonzeroViewOffset,
8907                                                        const bool bind2)
8908     : vkt::TestInstance(context)
8909     , m_updateMethod(updateMethod)
8910     , m_descriptorType(descriptorType)
8911     , m_descriptorSetCount(descriptorSetCount)
8912     , m_shaderInterface(shaderInterface)
8913     , m_nonzeroViewOffset(nonzeroViewOffset)
8914     , m_bind2(bind2)
8915     , m_vki(context.getDeviceInterface())
8916     , m_device(context.getDevice())
8917     , m_queue(context.getUniversalQueue())
8918     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
8919     , m_allocator(context.getDefaultAllocator())
8920 #ifndef CTS_USES_VULKANSC
8921     , m_updateTemplates()
8922 #endif
8923     , m_result(m_vki, m_device, m_allocator)
8924     , m_texelBuffers(context, m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount, m_shaderInterface,
8925                      m_nonzeroViewOffset)
8926 #ifndef CTS_USES_VULKANSC
8927     , m_updateRegistry()
8928 #endif
8929     , m_updateBuilder()
8930     , m_descriptorsPerSet()
8931 {
8932 }
8933 
createDescriptorSetLayout(uint32_t setNdx) const8934 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
8935 {
8936     vk::DescriptorSetLayoutBuilder builder;
8937     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
8938     uint32_t binding                                = 0;
8939 
8940 #ifndef CTS_USES_VULKANSC
8941     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
8942         m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
8943     {
8944         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
8945     }
8946 #endif
8947 
8948     if (setNdx == 0)
8949         builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
8950                                         binding++);
8951 
8952     switch (m_shaderInterface)
8953     {
8954     case SHADER_INPUT_SINGLE_DESCRIPTOR:
8955         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8956         break;
8957 
8958     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
8959         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8960         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8961         break;
8962 
8963     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
8964         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding);
8965         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2);
8966         break;
8967 
8968     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
8969         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
8970         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
8971         break;
8972 
8973     case SHADER_INPUT_DESCRIPTOR_ARRAY:
8974         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
8975         break;
8976 
8977     default:
8978         DE_FATAL("Impossible");
8979     }
8980 
8981     return builder.build(m_vki, m_device, extraFlags);
8982 }
8983 
createDescriptorPool(void) const8984 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool(void) const
8985 {
8986     return vk::DescriptorPoolBuilder()
8987         .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
8988         .addType(m_descriptorType,
8989                  getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
8990         .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
8991                getDescriptorSetCount(m_descriptorSetCount));
8992 }
8993 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)8994 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
8995                                                                               vk::VkDescriptorSetLayout layout,
8996                                                                               uint32_t setNdx)
8997 {
8998     const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
8999                                                        pool, 1u, &layout};
9000 
9001     vk::Move<vk::VkDescriptorSet> descriptorSet;
9002     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
9003         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9004     {
9005         descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
9006     }
9007     else
9008     {
9009         descriptorSet = vk::Move<vk::VkDescriptorSet>();
9010     }
9011 
9012 #ifndef CTS_USES_VULKANSC
9013     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
9014     {
9015         writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx);
9016     }
9017     else
9018 #endif
9019         if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
9020     {
9021         writeDescriptorSet(*descriptorSet, setNdx);
9022     }
9023 
9024     return descriptorSet;
9025 }
9026 
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)9027 void TexelBufferComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
9028 {
9029     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
9030         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
9031     const vk::VkBufferView texelBufferInfos[2] = {
9032         m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface)),
9033         m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)};
9034     uint32_t binding        = 0u;
9035     uint32_t numDescriptors = 0u;
9036 
9037     // result
9038     if (setNdx == 0)
9039     {
9040         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9041                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
9042         numDescriptors++;
9043     }
9044 
9045     // texel buffers
9046     switch (m_shaderInterface)
9047     {
9048     case SHADER_INPUT_SINGLE_DESCRIPTOR:
9049         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9050                                     m_descriptorType, &texelBufferInfos[0]);
9051         numDescriptors++;
9052         break;
9053 
9054     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9055         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9056                                     m_descriptorType, &texelBufferInfos[0]);
9057         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9058                                     m_descriptorType, &texelBufferInfos[1]);
9059         numDescriptors += 2;
9060         break;
9061 
9062     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9063         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
9064                                     m_descriptorType, &texelBufferInfos[0]);
9065         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
9066                                     m_descriptorType, &texelBufferInfos[1]);
9067         numDescriptors += 2;
9068         break;
9069 
9070     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9071         m_updateBuilder.writeSingle(descriptorSet,
9072                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
9073                                     m_descriptorType, &texelBufferInfos[0]);
9074         m_updateBuilder.writeSingle(descriptorSet,
9075                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
9076                                     m_descriptorType, &texelBufferInfos[1]);
9077         numDescriptors += 2;
9078         break;
9079 
9080     case SHADER_INPUT_DESCRIPTOR_ARRAY:
9081         m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
9082                                    m_descriptorType, 2u, texelBufferInfos);
9083         numDescriptors++;
9084         break;
9085 
9086     default:
9087         DE_FATAL("Impossible");
9088     }
9089 
9090     m_descriptorsPerSet.push_back(numDescriptors);
9091 
9092     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
9093     {
9094         m_updateBuilder.update(m_vki, m_device);
9095         m_updateBuilder.clear();
9096     }
9097 }
9098 
9099 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)9100 void TexelBufferComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
9101                                                                 vk::VkDescriptorSetLayout layout, uint32_t setNdx,
9102                                                                 bool withPush, vk::VkPipelineLayout pipelineLayout)
9103 {
9104     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
9105         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
9106     const vk::VkBufferView texelBufferInfos[2] = {
9107         m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface)),
9108         m_texelBuffers.getBufferView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1)};
9109     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
9110     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
9111         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
9112         DE_NULL,
9113         0,
9114         0,       // updateCount
9115         DE_NULL, // pUpdates
9116         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
9117                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
9118         layout,
9119         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
9120         pipelineLayout,
9121         setNdx};
9122     uint32_t binding = 0u;
9123     uint32_t offset  = 0u;
9124     RawUpdateRegistry updateRegistry;
9125 
9126     if (setNdx == 0)
9127         updateRegistry.addWriteObject(resultInfo);
9128 
9129     updateRegistry.addWriteObject(texelBufferInfos[0]);
9130     updateRegistry.addWriteObject(texelBufferInfos[1]);
9131 
9132     // result
9133     if (setNdx == 0)
9134         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
9135                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
9136 
9137     // texel buffers
9138     switch (m_shaderInterface)
9139     {
9140     case SHADER_INPUT_SINGLE_DESCRIPTOR:
9141         updateEntries.push_back(
9142             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9143         break;
9144 
9145     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9146         updateEntries.push_back(
9147             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9148         updateEntries.push_back(
9149             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9150         break;
9151 
9152     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9153         updateEntries.push_back(
9154             createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
9155         updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
9156                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
9157         break;
9158 
9159     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9160         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
9161                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
9162         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
9163                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
9164         break;
9165 
9166     case SHADER_INPUT_DESCRIPTOR_ARRAY:
9167         updateEntries.push_back(createTemplateBinding(binding++, 0, 2, m_descriptorType,
9168                                                       updateRegistry.getWriteObjectOffset(offset++),
9169                                                       sizeof(texelBufferInfos[0])));
9170         break;
9171 
9172     default:
9173         DE_FATAL("Impossible");
9174     }
9175 
9176     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
9177     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
9178 
9179     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
9180         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
9181     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
9182     m_updateRegistry.push_back(updateRegistry);
9183 
9184     if (!withPush)
9185     {
9186         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates[setNdx],
9187                                               m_updateRegistry.back().getRawPointer());
9188     }
9189 }
9190 #endif
9191 
iterate(void)9192 tcu::TestStatus TexelBufferComputeInstance::iterate(void)
9193 {
9194     logTestPlan();
9195     return testResourceAccess();
9196 }
9197 
logTestPlan(void) const9198 void TexelBufferComputeInstance::logTestPlan(void) const
9199 {
9200     std::ostringstream msg;
9201 
9202     msg << "Fetching 4 values from image in compute shader.\n"
9203         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
9204                                                                     "Multiple descriptor sets. ")
9205         << "Each descriptor set contains "
9206         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
9207             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
9208             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
9209             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
9210             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
9211                                                                                      (const char *)DE_NULL)
9212         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
9213         << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
9214         << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
9215 
9216     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
9217     {
9218         msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
9219 
9220         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
9221         {
9222             const int srcResourceNdx = (resultNdx % 2); // ABAB source
9223             msg << " from texelBuffer " << srcResourceNdx;
9224         }
9225 
9226         msg << "\n";
9227     }
9228 
9229     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
9230 }
9231 
testResourceAccess(void)9232 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess(void)
9233 {
9234     const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
9235     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
9236     std::vector<DescriptorSetHandleSp> descriptorSets;
9237     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
9238     std::vector<vk::VkDescriptorSet> setHandles;
9239 
9240     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9241     {
9242         vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
9243         vk::Move<vk::VkDescriptorSet> set          = createDescriptorSet(*descriptorPool, *layout, setNdx);
9244 
9245         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
9246         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
9247 
9248         layoutHandles.push_back(**descriptorSetLayouts.back());
9249         setHandles.push_back(**descriptorSets.back());
9250 
9251         // Add an empty descriptor set layout between sets 0 and 2
9252         if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
9253         {
9254             vk::DescriptorSetLayoutBuilder emptyBuilder;
9255             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
9256                 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
9257 
9258             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
9259             layoutHandles.push_back(**descriptorSetLayouts.back());
9260         }
9261     }
9262 
9263     const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
9264                                    &layoutHandles.front());
9265     const uint32_t *const dynamicOffsets                = DE_NULL;
9266     const int numDynamicOffsets                         = 0;
9267     const vk::VkBufferMemoryBarrier *const preBarriers  = m_texelBuffers.getBufferInitBarriers();
9268     const int numPreBarriers                            = m_texelBuffers.getNumTexelBuffers();
9269     const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
9270     const int numPostBarriers                           = 1;
9271 
9272     const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
9273                                  tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
9274                                  numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
9275                                  postBarriers, m_bind2);
9276 
9277     tcu::Vec4 results[4];
9278     bool anyResultSet = false;
9279     bool allResultsOk = true;
9280 
9281 #ifndef CTS_USES_VULKANSC
9282     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9283     {
9284         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9285             writeDescriptorSetWithTemplate(DE_NULL, layoutHandles[setNdx], setNdx, true, pipeline.getPipelineLayout());
9286 
9287         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
9288     }
9289     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
9290     {
9291         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9292             writeDescriptorSet(DE_NULL, setNdx);
9293 
9294         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
9295     }
9296     else
9297 #endif
9298     {
9299         compute.submitAndWait(m_queueFamilyIndex, m_queue);
9300     }
9301     m_result.readResultContentsTo(&results);
9302 
9303     // verify
9304     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
9305     {
9306         const tcu::Vec4 result              = results[resultNdx];
9307         const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
9308 
9309         tcu::Vec4 reference = tcu::Vec4(0.0f);
9310         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9311             reference += m_texelBuffers.fetchTexelValue(resultNdx, setNdx);
9312 
9313         reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
9314 
9315         if (result != tcu::Vec4(-1.0f))
9316             anyResultSet = true;
9317 
9318         if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
9319         {
9320             allResultsOk = false;
9321 
9322             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
9323                                                 << reference << ", got " << result << tcu::TestLog::EndMessage;
9324         }
9325     }
9326 
9327     // read back and verify
9328     if (allResultsOk)
9329         return tcu::TestStatus::pass("Pass");
9330     else if (anyResultSet)
9331         return tcu::TestStatus::fail("Invalid result values");
9332     else
9333     {
9334         m_context.getTestContext().getLog()
9335             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
9336         return tcu::TestStatus::fail("Result buffer was not written to");
9337     }
9338 }
9339 
9340 class TexelBufferDescriptorCase : public QuadrantRendederCase
9341 {
9342 public:
9343     enum
9344     {
9345         FLAG_VIEW_OFFSET = (1u << 1u),
9346     };
9347     // enum continues where resource flags ends
9348     DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
9349 
9350     TexelBufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
9351                               bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
9352                               vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9353                               DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
9354                               uint32_t flags, const bool m_bind2);
9355 
9356     void checkSupport(Context &context) const;
9357 
9358 private:
9359     std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
9360     std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
9361     std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
9362     std::string genNoAccessSource(void) const;
9363 
9364     vkt::TestInstance *createInstance(vkt::Context &context) const;
9365 
9366     const DescriptorUpdateMethod m_updateMethod;
9367     const bool m_isPrimaryCmdBuf;
9368     const vk::VkDescriptorType m_descriptorType;
9369     const DescriptorSetCount m_descriptorSetCount;
9370     const ShaderInputInterface m_shaderInterface;
9371     const bool m_nonzeroViewOffset;
9372     const bool m_bind2;
9373 };
9374 
TexelBufferDescriptorCase(tcu::TestContext & testCtx,DescriptorUpdateMethod updateMethod,const char * name,bool isPrimaryCmdBuf,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,uint32_t flags,const bool bind2)9375 TexelBufferDescriptorCase::TexelBufferDescriptorCase(
9376     tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name, bool isPrimaryCmdBuf,
9377     vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9378     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags, const bool bind2)
9379     : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
9380     , m_updateMethod(updateMethod)
9381     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
9382     , m_descriptorType(descriptorType)
9383     , m_descriptorSetCount(descriptorSetCount)
9384     , m_shaderInterface(shaderInterface)
9385     , m_nonzeroViewOffset(((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
9386     , m_bind2(bind2)
9387 {
9388 }
9389 
checkSupport(Context & context) const9390 void TexelBufferDescriptorCase::checkSupport(Context &context) const
9391 {
9392     if (m_bind2)
9393         context.requireDeviceFunctionality("VK_KHR_maintenance6");
9394 }
9395 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const9396 std::string TexelBufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
9397 {
9398     DE_UNREF(stage);
9399     return "#extension GL_EXT_texture_buffer : require\n";
9400 }
9401 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const9402 std::string TexelBufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage,
9403                                                                int numUsedBindings) const
9404 {
9405     DE_UNREF(stage);
9406 
9407     const bool isUniform              = isUniformDescriptorType(m_descriptorType);
9408     const char *const storageType     = (isUniform) ? ("textureBuffer ") : ("readonly imageBuffer ");
9409     const char *const formatQualifier = (isUniform) ? ("") : (", rgba8");
9410     const uint32_t numSets            = getDescriptorSetCount(m_descriptorSetCount);
9411 
9412     std::ostringstream buf;
9413 
9414     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9415     {
9416         // Result buffer is bound only to the first descriptor set in compute shader cases
9417         const int descBinding =
9418             numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
9419         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9420         const uint32_t descriptorSet    = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
9421 
9422         switch (m_shaderInterface)
9423         {
9424         case SHADER_INPUT_SINGLE_DESCRIPTOR:
9425             buf << "layout(set = " << descriptorSet
9426                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9427                        "u_texelBuffer"
9428                 << setNdxPostfix << ";\n";
9429             break;
9430         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9431             buf << "layout(set = " << descriptorSet
9432                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9433                        "u_texelBuffer"
9434                 << setNdxPostfix
9435                 << "A;\n"
9436                    "layout(set = "
9437                 << descriptorSet
9438                 << ", binding = " + de::toString(descBinding + 1) + formatQualifier + ") uniform highp " + storageType +
9439                        "u_texelBuffer"
9440                 << setNdxPostfix << "B;\n";
9441             break;
9442         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9443             buf << "layout(set = " << descriptorSet
9444                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9445                        "u_texelBuffer"
9446                 << setNdxPostfix
9447                 << "A;\n"
9448                    "layout(set = "
9449                 << descriptorSet
9450                 << ", binding = " + de::toString(descBinding + 2) + formatQualifier + ") uniform highp " + storageType +
9451                        "u_texelBuffer"
9452                 << setNdxPostfix << "B;\n";
9453             break;
9454         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9455             buf << "layout(set = " << descriptorSet
9456                 << ", binding = " + de::toString(getArbitraryBindingIndex(0)) + formatQualifier + ") uniform highp " +
9457                        storageType + "u_texelBuffer"
9458                 << setNdxPostfix
9459                 << "A;\n"
9460                    "layout(set = "
9461                 << descriptorSet
9462                 << ", binding = " + de::toString(getArbitraryBindingIndex(1)) + formatQualifier + ") uniform highp " +
9463                        storageType + "u_texelBuffer"
9464                 << setNdxPostfix << "B;\n";
9465             break;
9466         case SHADER_INPUT_DESCRIPTOR_ARRAY:
9467             buf << "layout(set = " << descriptorSet
9468                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9469                        "u_texelBuffer"
9470                 << setNdxPostfix << "[2];\n";
9471             break;
9472         default:
9473             DE_FATAL("Impossible");
9474             return "";
9475         }
9476     }
9477     return buf.str();
9478 }
9479 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const9480 std::string TexelBufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
9481 {
9482     DE_UNREF(stage);
9483 
9484     const char *const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? ("") :
9485                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? ("A") :
9486                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") :
9487                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? ("A") :
9488                                        (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") :
9489                                                                                               (DE_NULL);
9490     const char *const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? ("") :
9491                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? ("B") :
9492                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") :
9493                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? ("B") :
9494                                        (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") :
9495                                                                                               (DE_NULL);
9496     const char *const fetchFunc      = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
9497     const uint32_t numSets           = getDescriptorSetCount(m_descriptorSetCount);
9498 
9499     std::ostringstream buf;
9500 
9501     buf << "    result_color = vec4(0.0);\n";
9502 
9503     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9504     {
9505         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9506 
9507         buf << "    if (quadrant_id == 0)\n"
9508             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9509             << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
9510             << "    else if (quadrant_id == 1)\n"
9511             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9512             << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
9513             << "    else if (quadrant_id == 2)\n"
9514             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9515             << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
9516             << "    else\n"
9517             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9518             << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
9519     }
9520 
9521     if (getDescriptorSetCount(m_descriptorSetCount) > 1)
9522         buf << "    result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
9523 
9524     return buf.str();
9525 }
9526 
genNoAccessSource(void) const9527 std::string TexelBufferDescriptorCase::genNoAccessSource(void) const
9528 {
9529     return "    if (quadrant_id == 1 || quadrant_id == 2)\n"
9530            "        result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
9531            "    else\n"
9532            "        result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
9533 }
9534 
createInstance(vkt::Context & context) const9535 vkt::TestInstance *TexelBufferDescriptorCase::createInstance(vkt::Context &context) const
9536 {
9537     verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
9538                         m_updateMethod, m_descriptorType, m_activeStages);
9539 
9540     if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
9541     {
9542         DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
9543         return new TexelBufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
9544                                               m_shaderInterface, m_nonzeroViewOffset, m_bind2);
9545     }
9546     else
9547         return new TexelBufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
9548                                              m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
9549                                              m_nonzeroViewOffset, m_bind2);
9550 }
9551 
createShaderAccessImageTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface dimension,uint32_t resourceFlags,const bool bind2)9552 void createShaderAccessImageTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9553                                   vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9554                                   vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9555                                   ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9556 {
9557     static const struct
9558     {
9559         vk::VkImageViewType viewType;
9560         const char *name;
9561         uint32_t flags;
9562     } s_imageTypes[] = {
9563         {vk::VK_IMAGE_VIEW_TYPE_1D, "1d", 0u},
9564         {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9565         {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9566 
9567         {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", 0u},
9568         {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9569         {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9570 
9571         {vk::VK_IMAGE_VIEW_TYPE_2D, "2d", 0u},
9572         {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9573         {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9574 
9575         {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", 0u},
9576         {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9577         {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9578 
9579         {vk::VK_IMAGE_VIEW_TYPE_3D, "3d", 0u},
9580         {vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9581         // no 3d array textures
9582 
9583         {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", 0u},
9584         {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9585         {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9586 
9587         {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", 0u},
9588         {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9589         {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE}};
9590 
9591     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
9592     {
9593         // never overlap
9594         DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
9595 
9596         // skip some image view variations to avoid unnecessary bloating
9597         if ((descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER) &&
9598             (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9599             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9600             continue;
9601 
9602         if ((dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9603             (activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) &&
9604             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9605             continue;
9606 
9607         if ((dimension == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) &&
9608             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9609             continue;
9610 
9611         if ((descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS) &&
9612             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9613             continue;
9614 
9615         group->addChild(new ImageDescriptorCase(group->getTestContext(), s_imageTypes[ndx].name, isPrimaryCmdBuf,
9616                                                 updateMethod, descriptorType, exitingStages, activeStages,
9617                                                 descriptorSetCount, dimension, s_imageTypes[ndx].viewType,
9618                                                 s_imageTypes[ndx].flags | resourceFlags, bind2));
9619     }
9620 }
9621 
createShaderAccessTexelBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface dimension,uint32_t resourceFlags,const bool bind2)9622 void createShaderAccessTexelBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9623                                         DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9624                                         vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9625                                         DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9626                                         uint32_t resourceFlags, const bool bind2)
9627 {
9628     DE_ASSERT(resourceFlags == 0);
9629     DE_UNREF(resourceFlags);
9630 
9631     static const struct
9632     {
9633         const char *name;
9634         uint32_t flags;
9635     } s_texelBufferTypes[] = {
9636         // View offset is zero
9637         {"offset_zero", 0u},
9638         // View offset is non-zero
9639         {"offset_nonzero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET},
9640     };
9641 
9642     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
9643     {
9644         group->addChild(new TexelBufferDescriptorCase(
9645             group->getTestContext(), updateMethod, s_texelBufferTypes[ndx].name, isPrimaryCmdBuf, descriptorType,
9646             exitingStages, activeStages, descriptorSetCount, dimension, s_texelBufferTypes[ndx].flags, bind2));
9647     }
9648 }
9649 
createShaderAccessBufferTests(tcu::TestCaseGroup * group,bool isPrimaryCmdBuf,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount,ShaderInputInterface dimension,uint32_t resourceFlags,const bool bind2)9650 void createShaderAccessBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9651                                    vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9652                                    vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9653                                    ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9654 {
9655     DE_ASSERT(resourceFlags == 0u);
9656     DE_UNREF(resourceFlags);
9657 
9658     static const struct
9659     {
9660         const char *name;
9661         bool isForDynamicCases;
9662         uint32_t flags;
9663     } s_bufferTypes[] = {
9664         {"offset_view_zero", false, 0u},
9665         {"offset_view_nonzero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET},
9666 
9667         {"offset_view_zero_dynamic_zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9668         {"offset_view_zero_dynamic_nonzero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9669         {"offset_view_nonzero_dynamic_zero", true,
9670          BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9671         {"offset_view_nonzero_dynamic_nonzero", true,
9672          BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9673     };
9674 
9675     const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
9676 
9677     if (isDynamicCase)
9678     {
9679         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9680             updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9681         {
9682             // Can't support push descriptor sets with dynamic UBOs or SSBOs
9683             return;
9684         }
9685     }
9686 
9687     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
9688     {
9689         if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
9690             group->addChild(new BufferDescriptorCase(group->getTestContext(), updateMethod, s_bufferTypes[ndx].name,
9691                                                      isPrimaryCmdBuf, descriptorType, exitingStages, activeStages,
9692                                                      descriptorSetCount, dimension, s_bufferTypes[ndx].flags, bind2));
9693     }
9694 }
9695 
9696 } // namespace
9697 
createShaderAccessTests(tcu::TestContext & testCtx)9698 tcu::TestCaseGroup *createShaderAccessTests(tcu::TestContext &testCtx)
9699 {
9700     static const struct
9701     {
9702         const bool isPrimary;
9703         const char *name;
9704     } s_bindTypes[] = {
9705         // Bind in primary command buffer
9706         {true, "primary_cmd_buf"},
9707         // Bind in secondary command buffer
9708         {false, "secondary_cmd_buf"},
9709     };
9710     static const struct
9711     {
9712         const DescriptorUpdateMethod method;
9713         const char *name;
9714     } s_updateMethods[] = {
9715         {DESCRIPTOR_UPDATE_METHOD_NORMAL, ""},
9716 #ifndef CTS_USES_VULKANSC
9717         // Use descriptor update templates
9718         {DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, "with_template"},
9719         // Use push descriptor updates
9720         {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, "with_push"},
9721         // Use push descriptor update templates
9722         {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, "with_push_template"},
9723 #endif
9724     };
9725     static const struct
9726     {
9727         const vk::VkDescriptorType descriptorType;
9728         const char *name;
9729         const char *description;
9730         uint32_t flags;
9731     } s_descriptorTypes[] = {
9732         {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u},
9733         {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",
9734          RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9735         {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable",
9736          "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u},
9737         {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable",
9738          "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9739         // \note No way to access SAMPLED_IMAGE without a sampler
9740         //{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u                                },
9741         {vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u},
9742         {vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",
9743          0u},
9744         {vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",
9745          0u},
9746         {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u},
9747         {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u},
9748         {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic",
9749          "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u},
9750         {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic",
9751          "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u},
9752     };
9753     static const struct
9754     {
9755         const char *name;
9756         vk::VkShaderStageFlags existingStages; //!< stages that exists
9757         vk::VkShaderStageFlags activeStages;   //!< stages that access resource
9758         bool supportsSecondaryCmdBufs;
9759     } s_shaderStages[] = {
9760         // No accessing stages
9761         {
9762             "no_access",
9763             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9764             0u,
9765             true,
9766         },
9767         // Vertex stage
9768         {
9769             "vertex",
9770             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9771             vk::VK_SHADER_STAGE_VERTEX_BIT,
9772             true,
9773         },
9774         // Tessellation control stage
9775         {
9776             "tess_ctrl",
9777             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9778                 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9779             vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
9780             true,
9781         },
9782         // Tessellation evaluation stage
9783         {
9784             "tess_eval",
9785             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9786                 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9787             vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
9788             true,
9789         },
9790         // Geometry stage
9791         {
9792             "geometry",
9793             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9794             vk::VK_SHADER_STAGE_GEOMETRY_BIT,
9795             true,
9796         },
9797         // Fragment stage
9798         {
9799             "fragment",
9800             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9801             vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9802             true,
9803         },
9804         // Compute stage
9805         {
9806             "compute",
9807             vk::VK_SHADER_STAGE_COMPUTE_BIT,
9808             vk::VK_SHADER_STAGE_COMPUTE_BIT,
9809             false,
9810         },
9811         // Vertex and fragment stages
9812         {
9813             "vertex_fragment",
9814             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9815             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9816             true,
9817         }};
9818     static const struct
9819     {
9820         ShaderInputInterface dimension;
9821         const char *name;
9822     } s_variableDimensions[] = {
9823         {SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor"},
9824         {SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, "multiple_contiguous_descriptors"},
9825         {SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, "multiple_discontiguous_descriptors"},
9826         {SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS, "multiple_arbitrary_descriptors"},
9827         {SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array"},
9828     };
9829     static const struct
9830     {
9831         const bool bind2;
9832         const char *name;
9833         const char *description;
9834     } s_bindCommand[] = {
9835         {false, "bind", "use_vkCmdBindDescriptors"},
9836         {true, "bind2", "use vkCmdBindDescriptors2"},
9837     };
9838 
9839     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access"));
9840 
9841     // .primary_cmd_buf...
9842     for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
9843     {
9844         de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name));
9845 
9846         for (int bindCommandNdx = 0; bindCommandNdx < DE_LENGTH_OF_ARRAY(s_bindCommand); ++bindCommandNdx)
9847         {
9848             de::MovePtr<tcu::TestCaseGroup> bindCommandGroup(
9849                 new tcu::TestCaseGroup(testCtx, s_bindCommand[bindCommandNdx].name));
9850 
9851             for (int updateMethodNdx = 0; updateMethodNdx < DE_LENGTH_OF_ARRAY(s_updateMethods); ++updateMethodNdx)
9852             {
9853                 de::MovePtr<tcu::TestCaseGroup> updateMethodGroup(
9854                     new tcu::TestCaseGroup(testCtx, s_updateMethods[updateMethodNdx].name));
9855 
9856                 // .sampler, .combined_image_sampler, other resource types ...
9857                 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
9858                 {
9859                     de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(
9860                         testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
9861 
9862                     for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
9863                     {
9864                         if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
9865                         {
9866                             de::MovePtr<tcu::TestCaseGroup> stageGroup(
9867                                 new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name));
9868                             de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(
9869                                 testCtx, "multiple_descriptor_sets", "Multiple descriptor sets"));
9870                             de::MovePtr<tcu::TestCaseGroup> multipleDiscontiguousGroup(
9871                                 new tcu::TestCaseGroup(testCtx, "multiple_discontiguous_descriptor_sets",
9872                                                        "Multiple discontiguous descriptor sets"));
9873 
9874                             for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions);
9875                                  ++dimensionNdx)
9876                             {
9877                                 de::MovePtr<tcu::TestCaseGroup> dimensionSingleDescriptorSetGroup(
9878                                     new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9879                                 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDescriptorSetsGroup(
9880                                     new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9881                                 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDiscontiguousDescriptorSetsGroup(
9882                                     new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9883                                 void (*createTestsFunc)(
9884                                     tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9885                                     DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9886                                     vk::VkShaderStageFlags existingStages, vk::VkShaderStageFlags activeStages,
9887                                     DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9888                                     uint32_t resourceFlags, const bool bind2);
9889 
9890                                 switch (s_descriptorTypes[descriptorNdx].descriptorType)
9891                                 {
9892                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
9893                                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
9894                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
9895                                     createTestsFunc = createShaderAccessImageTests;
9896                                     break;
9897 
9898                                 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
9899                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
9900                                     createTestsFunc = createShaderAccessTexelBufferTests;
9901                                     break;
9902 
9903                                 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
9904                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
9905                                 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
9906                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
9907                                     createTestsFunc = createShaderAccessBufferTests;
9908                                     break;
9909 
9910                                 default:
9911                                     createTestsFunc = DE_NULL;
9912                                     DE_FATAL("Impossible");
9913                                 }
9914 
9915                                 if (createTestsFunc)
9916                                 {
9917                                     createTestsFunc(
9918                                         dimensionSingleDescriptorSetGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9919                                         s_updateMethods[updateMethodNdx].method,
9920                                         s_descriptorTypes[descriptorNdx].descriptorType,
9921                                         s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9922                                         DESCRIPTOR_SET_COUNT_SINGLE, s_variableDimensions[dimensionNdx].dimension,
9923                                         s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9924 
9925                                     createTestsFunc(
9926                                         dimensionMultipleDescriptorSetsGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9927                                         s_updateMethods[updateMethodNdx].method,
9928                                         s_descriptorTypes[descriptorNdx].descriptorType,
9929                                         s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9930                                         DESCRIPTOR_SET_COUNT_MULTIPLE, s_variableDimensions[dimensionNdx].dimension,
9931                                         s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9932 
9933                                     createTestsFunc(
9934                                         dimensionMultipleDiscontiguousDescriptorSetsGroup.get(),
9935                                         s_bindTypes[bindTypeNdx].isPrimary, s_updateMethods[updateMethodNdx].method,
9936                                         s_descriptorTypes[descriptorNdx].descriptorType,
9937                                         s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9938                                         DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS,
9939                                         s_variableDimensions[dimensionNdx].dimension,
9940                                         s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9941                                 }
9942                                 else
9943                                     DE_FATAL("Impossible");
9944 
9945                                 stageGroup->addChild(dimensionSingleDescriptorSetGroup.release());
9946 
9947                                 // Only one descriptor set layout can be created with VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR set
9948                                 if (s_updateMethods[updateMethodNdx].method == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9949                                     s_updateMethods[updateMethodNdx].method ==
9950                                         DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9951                                     continue;
9952 
9953                                 multipleGroup->addChild(dimensionMultipleDescriptorSetsGroup.release());
9954                                 multipleDiscontiguousGroup->addChild(
9955                                     dimensionMultipleDiscontiguousDescriptorSetsGroup.release());
9956                             }
9957 
9958                             stageGroup->addChild(multipleGroup.release());
9959                             stageGroup->addChild(multipleDiscontiguousGroup.release());
9960                             typeGroup->addChild(stageGroup.release());
9961                         }
9962                     }
9963 
9964                     if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9965                     {
9966                         updateMethodGroup->addChild(typeGroup.release());
9967                     }
9968                     else
9969                     {
9970                         bindCommandGroup->addChild(typeGroup.release());
9971                     }
9972                 }
9973 
9974                 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9975                 {
9976                     bindCommandGroup->addChild(updateMethodGroup.release());
9977                 }
9978             }
9979             bindGroup->addChild(bindCommandGroup.release());
9980         }
9981 
9982         group->addChild(bindGroup.release());
9983     }
9984 
9985     return group.release();
9986 }
9987 
9988 } // namespace BindingModel
9989 } // namespace vkt
9990