• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_push_descriptor"))
175             extensionNames.push_back("VK_KHR_push_descriptor");
176         break;
177 
178     case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE:
179         if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_push_descriptor"))
180             extensionNames.push_back("VK_KHR_push_descriptor");
181     // Fallthrough
182     case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE:
183         if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_descriptor_update_template"))
184             extensionNames.push_back("VK_KHR_descriptor_update_template");
185         break;
186 
187     case DESCRIPTOR_UPDATE_METHOD_NORMAL:
188         // no extensions needed
189         break;
190 
191     default:
192         DE_FATAL("Impossible");
193     }
194 
195     numExtensionsNeeded = extensionNames.size();
196 
197     if (numExtensionsNeeded > 0)
198     {
199         for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++)
200         {
201             for (size_t requiredExtNdx = 0; requiredExtNdx < extensionNames.size(); requiredExtNdx++)
202             {
203                 if (deviceExtensions[deviceExtNdx] == extensionNames[requiredExtNdx])
204                 {
205                     --numExtensionsNeeded;
206                     break;
207                 }
208             }
209 
210             if (numExtensionsNeeded == 0)
211                 break;
212         }
213 
214         if (numExtensionsNeeded > 0)
215         {
216             TCU_THROW(NotSupportedError,
217                       (stringifyDescriptorUpdateMethod(updateMethod) + " tests are not supported").c_str());
218         }
219     }
220 
221     switch (descType)
222     {
223     case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
224     case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
225     case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
226     case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
227     case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
228     case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
229         // These are supported in all stages
230         break;
231 
232     case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
233     case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
234     case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
235     case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
236         if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
237                             vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT))
238         {
239             if (!deviceFeatures.vertexPipelineStoresAndAtomics)
240                 TCU_THROW(NotSupportedError,
241                           (de::toString(descType) + " is not supported in the vertex pipeline").c_str());
242         }
243 
244         if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
245         {
246             if (!deviceFeatures.fragmentStoresAndAtomics)
247                 TCU_THROW(NotSupportedError,
248                           (de::toString(descType) + " is not supported in fragment shaders").c_str());
249         }
250         break;
251 
252     default:
253         DE_FATAL("Impossible");
254     }
255 
256     if (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !deviceFeatures.imageCubeArray)
257         TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
258 }
259 
viewTypeToImageType(vk::VkImageViewType type)260 vk::VkImageType viewTypeToImageType(vk::VkImageViewType type)
261 {
262     switch (type)
263     {
264     case vk::VK_IMAGE_VIEW_TYPE_1D:
265     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
266         return vk::VK_IMAGE_TYPE_1D;
267     case vk::VK_IMAGE_VIEW_TYPE_2D:
268     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
269         return vk::VK_IMAGE_TYPE_2D;
270     case vk::VK_IMAGE_VIEW_TYPE_3D:
271         return vk::VK_IMAGE_TYPE_3D;
272     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
273     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
274         return vk::VK_IMAGE_TYPE_2D;
275 
276     default:
277         DE_FATAL("Impossible");
278         return (vk::VkImageType)0;
279     }
280 }
281 
getImageLayoutForDescriptorType(vk::VkDescriptorType descType)282 vk::VkImageLayout getImageLayoutForDescriptorType(vk::VkDescriptorType descType)
283 {
284     if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
285         return vk::VK_IMAGE_LAYOUT_GENERAL;
286     else
287         return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
288 }
289 
getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid & srcImage)290 uint32_t getTextureLevelPyramidDataSize(const tcu::TextureLevelPyramid &srcImage)
291 {
292     uint32_t dataSize = 0;
293     for (int level = 0; level < srcImage.getNumLevels(); ++level)
294     {
295         const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
296 
297         // tightly packed
298         DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
299 
300         dataSize +=
301             srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
302     }
303     return dataSize;
304 }
305 
writeTextureLevelPyramidData(void * dst,uint32_t dstLen,const tcu::TextureLevelPyramid & srcImage,vk::VkImageViewType viewType,std::vector<vk::VkBufferImageCopy> * copySlices)306 void writeTextureLevelPyramidData(void *dst, uint32_t dstLen, const tcu::TextureLevelPyramid &srcImage,
307                                   vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy> *copySlices)
308 {
309     // \note cube is copied face-by-face
310     const uint32_t arraySize =
311         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
312             (srcImage.getLevel(0).getHeight()) :
313         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
314             (srcImage.getLevel(0).getDepth()) :
315         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
316         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
317                                                   (srcImage.getLevel(0).getDepth()) :
318                                                   ((uint32_t)0);
319     uint32_t levelOffset = 0;
320 
321     DE_ASSERT(arraySize != 0);
322 
323     for (int level = 0; level < srcImage.getNumLevels(); ++level)
324     {
325         const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
326         const tcu::PixelBufferAccess dstAccess(srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(),
327                                                (uint8_t *)dst + levelOffset);
328         const uint32_t dataSize =
329             srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
330         const uint32_t sliceDataSize = dataSize / arraySize;
331         const int32_t sliceHeight =
332             (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
333                 (1) :
334                 (srcAccess.getHeight());
335         const int32_t sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
336         const tcu::IVec3 sliceSize(srcAccess.getWidth(), sliceHeight, sliceDepth);
337 
338         // tightly packed
339         DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
340 
341         for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
342         {
343             const vk::VkBufferImageCopy copySlice = {
344                 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset
345                 (uint32_t)sliceSize.x(),                                  // bufferRowLength
346                 (uint32_t)sliceSize.y(),                                  // bufferImageHeight
347                 {
348                     vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
349                     (uint32_t)level,               // mipLevel
350                     (uint32_t)sliceNdx,            // arrayLayer
351                     1u,                            // arraySize
352                 },                                 // imageSubresource
353                 {
354                     0,
355                     0,
356                     0,
357                 }, // imageOffset
358                 {
359                     (uint32_t)sliceSize.x(),
360                     (uint32_t)sliceSize.y(),
361                     (uint32_t)sliceSize.z(),
362                 } // imageExtent
363             };
364             copySlices->push_back(copySlice);
365         }
366 
367         DE_ASSERT(arraySize * sliceDataSize == dataSize);
368 
369         tcu::copy(dstAccess, srcAccess);
370         levelOffset += dataSize;
371     }
372 
373     DE_ASSERT(dstLen == levelOffset);
374     DE_UNREF(dstLen);
375 }
376 
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkBuffer buffer,vk::MemoryRequirement requirement)377 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
378                                                         vk::Allocator &allocator, vk::VkBuffer buffer,
379                                                         vk::MemoryRequirement requirement)
380 {
381     const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer);
382     de::MovePtr<vk::Allocation> allocation      = allocator.allocate(requirements, requirement);
383 
384     VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
385     return allocation;
386 }
387 
allocateAndBindObjectMemory(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,vk::VkImage image,vk::MemoryRequirement requirement)388 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory(const vk::DeviceInterface &vki, vk::VkDevice device,
389                                                         vk::Allocator &allocator, vk::VkImage image,
390                                                         vk::MemoryRequirement requirement)
391 {
392     const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image);
393     de::MovePtr<vk::Allocation> allocation      = allocator.allocate(requirements, requirement);
394 
395     VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
396     return allocation;
397 }
398 
makeDescriptorImageInfo(vk::VkSampler sampler)399 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkSampler sampler)
400 {
401     return vk::makeDescriptorImageInfo(sampler, VK_NULL_HANDLE, (vk::VkImageLayout)0);
402 }
403 
makeDescriptorImageInfo(vk::VkImageView imageView,vk::VkImageLayout layout)404 vk::VkDescriptorImageInfo makeDescriptorImageInfo(vk::VkImageView imageView, vk::VkImageLayout layout)
405 {
406     return vk::makeDescriptorImageInfo(VK_NULL_HANDLE, imageView, layout);
407 }
408 
drawQuadrantReferenceResult(const tcu::PixelBufferAccess & dst,const tcu::Vec4 & c1,const tcu::Vec4 & c2,const tcu::Vec4 & c3,const tcu::Vec4 & c4)409 void drawQuadrantReferenceResult(const tcu::PixelBufferAccess &dst, const tcu::Vec4 &c1, const tcu::Vec4 &c2,
410                                  const tcu::Vec4 &c3, const tcu::Vec4 &c4)
411 {
412     tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1);
413     tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2),
414                c2);
415     tcu::clear(
416         tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3);
417     tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2,
418                                  dst.getHeight() - dst.getHeight() / 2),
419                c4);
420 }
421 
422 #ifndef CTS_USES_VULKANSC
createTemplateBinding(uint32_t binding,uint32_t arrayElement,uint32_t descriptorCount,vk::VkDescriptorType descriptorType,size_t offset,size_t stride)423 static const vk::VkDescriptorUpdateTemplateEntry createTemplateBinding(uint32_t binding, uint32_t arrayElement,
424                                                                        uint32_t descriptorCount,
425                                                                        vk::VkDescriptorType descriptorType,
426                                                                        size_t offset, size_t stride)
427 {
428     const vk::VkDescriptorUpdateTemplateEntry updateBinding = {binding,        arrayElement, descriptorCount,
429                                                                descriptorType, offset,       stride};
430 
431     return updateBinding;
432 }
433 
434 class RawUpdateRegistry
435 {
436 public:
437     RawUpdateRegistry(void);
438 
439     template <typename Type>
440     void addWriteObject(const Type &updateObject);
441     size_t getWriteObjectOffset(const uint32_t objectId);
442     const uint8_t *getRawPointer() const;
443 
444 private:
445     std::vector<uint8_t> m_updateEntries;
446     std::vector<size_t> m_updateEntryOffsets;
447     size_t m_nextOffset;
448 };
449 
RawUpdateRegistry(void)450 RawUpdateRegistry::RawUpdateRegistry(void) : m_updateEntries(), m_updateEntryOffsets(), m_nextOffset(0)
451 {
452 }
453 
454 template <typename Type>
addWriteObject(const Type & updateObject)455 void RawUpdateRegistry::addWriteObject(const Type &updateObject)
456 {
457     m_updateEntryOffsets.push_back(m_nextOffset);
458 
459     // in this case, elements <=> bytes
460     m_updateEntries.resize(m_nextOffset + sizeof(updateObject));
461     Type *t = reinterpret_cast<Type *>(m_updateEntries.data() + m_nextOffset);
462     *t      = updateObject;
463     m_nextOffset += sizeof(updateObject);
464 }
465 
getWriteObjectOffset(const uint32_t objectId)466 size_t RawUpdateRegistry::getWriteObjectOffset(const uint32_t objectId)
467 {
468     return m_updateEntryOffsets[objectId];
469 }
470 
getRawPointer() const471 const uint8_t *RawUpdateRegistry::getRawPointer() const
472 {
473     return m_updateEntries.data();
474 }
475 #endif
476 
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)477 void bindDescriptorSets(const vk::DeviceInterface &m_vki, vk::VkCommandBuffer cmdBuffer,
478                         vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
479                         vk::VkPipelineBindPoint bindPoint, vk::VkPipelineLayout layout, uint32_t first, uint32_t count,
480                         const vk::VkDescriptorSet *descriptorSets, uint32_t dynamicOffsetCount,
481                         const uint32_t *dynamicOffsets, bool bind2)
482 {
483     DE_UNREF(stageFlags);
484     DE_UNREF(existingStages);
485     if (bind2)
486     {
487 #ifndef CTS_USES_VULKANSC
488         vk::VkBindDescriptorSetsInfoKHR bindDescriptorSetsInfo = {
489             vk::VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO_KHR, // VkStructureType sType;
490             nullptr,                                             // const void* pNext;
491             existingStages,                                      // VkShaderStageFlags stageFlags;
492             layout,                                              // VkPipelineLayout layout;
493             first,                                               // uint32_t firstSet;
494             count,                                               // uint32_t descriptorSetCount;
495             descriptorSets,                                      // const VkDescriptorSet* pDescriptorSets;
496             dynamicOffsetCount,                                  // uint32_t dynamicOffsetCount;
497             dynamicOffsets                                       // const uint32_t* pDynamicOffsets;
498         };
499         m_vki.cmdBindDescriptorSets2(cmdBuffer, &bindDescriptorSetsInfo);
500 #endif
501     }
502     else
503     {
504         m_vki.cmdBindDescriptorSets(cmdBuffer, bindPoint, layout, first, count, descriptorSets, dynamicOffsetCount,
505                                     dynamicOffsets);
506     }
507 }
508 
509 class SingleTargetRenderInstance : public vkt::TestInstance
510 {
511 public:
512     SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2);
513 
514 private:
515     static vk::Move<vk::VkImage> createColorAttachment(const vk::DeviceInterface &vki, vk::VkDevice device,
516                                                        vk::Allocator &allocator, const tcu::TextureFormat &format,
517                                                        const tcu::UVec2 &size,
518                                                        de::MovePtr<vk::Allocation> *outAllocation);
519 
520     static vk::Move<vk::VkImageView> createColorAttachmentView(const vk::DeviceInterface &vki, vk::VkDevice device,
521                                                                const tcu::TextureFormat &format, vk::VkImage image);
522 
523     static vk::Move<vk::VkFramebuffer> createFramebuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
524                                                          vk::VkRenderPass renderpass,
525                                                          vk::VkImageView colorAttachmentView, const tcu::UVec2 &size);
526 
527     static vk::Move<vk::VkCommandPool> createCommandPool(const vk::DeviceInterface &vki, vk::VkDevice device,
528                                                          uint32_t queueFamilyIndex);
529 
530     virtual void logTestPlan(void) const                                                       = 0;
531     virtual void renderToTarget(void)                                                          = 0;
532     virtual tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const = 0;
533 
534     void readRenderTarget(tcu::TextureLevel &dst);
535     tcu::TestStatus iterate(void);
536 
537 protected:
538     const tcu::TextureFormat m_targetFormat;
539     const tcu::UVec2 m_targetSize;
540     const bool m_bind2;
541 
542     const vk::DeviceInterface &m_vki;
543     const vk::VkDevice m_device;
544     const vk::VkQueue m_queue;
545     const uint32_t m_queueFamilyIndex;
546     vk::Allocator &m_allocator;
547     de::MovePtr<vk::Allocation> m_colorAttachmentMemory;
548     const vk::Unique<vk::VkImage> m_colorAttachmentImage;
549     const vk::Unique<vk::VkImageView> m_colorAttachmentView;
550     const vk::Unique<vk::VkRenderPass> m_renderPass;
551     const vk::Unique<vk::VkFramebuffer> m_framebuffer;
552     const vk::Unique<vk::VkCommandPool> m_cmdPool;
553 
554     bool m_firstIteration;
555 };
556 
SingleTargetRenderInstance(Context & context,const tcu::UVec2 & size,const bool bind2)557 SingleTargetRenderInstance::SingleTargetRenderInstance(Context &context, const tcu::UVec2 &size, const bool bind2)
558     : vkt::TestInstance(context)
559     , m_targetFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
560     , m_targetSize(size)
561     , m_bind2(bind2)
562     , m_vki(context.getDeviceInterface())
563     , m_device(context.getDevice())
564     , m_queue(context.getUniversalQueue())
565     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
566     , m_allocator(context.getDefaultAllocator())
567     , m_colorAttachmentMemory(nullptr)
568     , m_colorAttachmentImage(
569           createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
570     , m_colorAttachmentView(createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
571     , m_renderPass(makeRenderPass(m_vki, m_device, vk::mapTextureFormat(m_targetFormat)))
572     , m_framebuffer(createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
573     , m_cmdPool(createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
574     , m_firstIteration(true)
575 {
576 }
577 
createColorAttachment(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,const tcu::TextureFormat & format,const tcu::UVec2 & size,de::MovePtr<vk::Allocation> * outAllocation)578 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment(const vk::DeviceInterface &vki,
579                                                                         vk::VkDevice device, vk::Allocator &allocator,
580                                                                         const tcu::TextureFormat &format,
581                                                                         const tcu::UVec2 &size,
582                                                                         de::MovePtr<vk::Allocation> *outAllocation)
583 {
584     const vk::VkImageCreateInfo imageInfo = {
585         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
586         nullptr,
587         (vk::VkImageCreateFlags)0,
588         vk::VK_IMAGE_TYPE_2D,                                                          // imageType
589         vk::mapTextureFormat(format),                                                  // format
590         {size.x(), size.y(), 1u},                                                      // extent
591         1,                                                                             // mipLevels
592         1,                                                                             // arraySize
593         vk::VK_SAMPLE_COUNT_1_BIT,                                                     // samples
594         vk::VK_IMAGE_TILING_OPTIMAL,                                                   // tiling
595         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
596         vk::VK_SHARING_MODE_EXCLUSIVE,                                                 // sharingMode
597         0u,                                                                            // queueFamilyCount
598         nullptr,                                                                       // pQueueFamilyIndices
599         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                                 // initialLayout
600     };
601 
602     vk::Move<vk::VkImage> image(vk::createImage(vki, device, &imageInfo));
603     de::MovePtr<vk::Allocation> allocation(
604         allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
605 
606     *outAllocation = allocation;
607     return image;
608 }
609 
createColorAttachmentView(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::TextureFormat & format,vk::VkImage image)610 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView(const vk::DeviceInterface &vki,
611                                                                                 vk::VkDevice device,
612                                                                                 const tcu::TextureFormat &format,
613                                                                                 vk::VkImage image)
614 {
615     const vk::VkImageViewCreateInfo createInfo = {
616         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
617         nullptr,
618         (vk::VkImageViewCreateFlags)0,
619         image,                        // image
620         vk::VK_IMAGE_VIEW_TYPE_2D,    // viewType
621         vk::mapTextureFormat(format), // format
622         vk::makeComponentMappingRGBA(),
623         {
624             vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
625             0u,                            // baseMipLevel
626             1u,                            // mipLevels
627             0u,                            // baseArrayLayer
628             1u,                            // arraySize
629         },
630     };
631 
632     return vk::createImageView(vki, device, &createInfo);
633 }
634 
createFramebuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkRenderPass renderpass,vk::VkImageView colorAttachmentView,const tcu::UVec2 & size)635 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer(const vk::DeviceInterface &vki,
636                                                                           vk::VkDevice device,
637                                                                           vk::VkRenderPass renderpass,
638                                                                           vk::VkImageView colorAttachmentView,
639                                                                           const tcu::UVec2 &size)
640 {
641     const vk::VkFramebufferCreateInfo framebufferCreateInfo = {
642         vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
643         nullptr,
644         (vk::VkFramebufferCreateFlags)0,
645         renderpass,           // renderPass
646         1u,                   // attachmentCount
647         &colorAttachmentView, // pAttachments
648         size.x(),             // width
649         size.y(),             // height
650         1,                    // layers
651     };
652 
653     return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
654 }
655 
createCommandPool(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t queueFamilyIndex)656 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool(const vk::DeviceInterface &vki,
657                                                                           vk::VkDevice device,
658                                                                           uint32_t queueFamilyIndex)
659 {
660     return vk::createCommandPool(vki, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
661 }
662 
readRenderTarget(tcu::TextureLevel & dst)663 void SingleTargetRenderInstance::readRenderTarget(tcu::TextureLevel &dst)
664 {
665     const uint64_t pixelDataSize = (uint64_t)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
666     const vk::VkBufferCreateInfo bufferCreateInfo = {
667         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
668         nullptr,
669         0u,                                   // flags
670         pixelDataSize,                        // size
671         vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
672         vk::VK_SHARING_MODE_EXCLUSIVE,        // sharingMode
673         0u,                                   // queueFamilyCount
674         nullptr,                              // pQueueFamilyIndices
675     };
676     const vk::Unique<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
677 
678     const de::MovePtr<vk::Allocation> bufferMemory =
679         allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
680 
681     const vk::Unique<vk::VkCommandBuffer> cmd(
682         vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
683 
684     // copy content to buffer
685     beginCommandBuffer(m_vki, *cmd);
686     copyImageToBuffer(m_vki, *cmd, *m_colorAttachmentImage, *buffer, tcu::IVec2(m_targetSize.x(), m_targetSize.y()));
687     endCommandBuffer(m_vki, *cmd);
688 
689     submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
690 
691     dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
692 
693     // copy data
694     invalidateAlloc(m_vki, m_device, *bufferMemory);
695     tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
696 }
697 
iterate(void)698 tcu::TestStatus SingleTargetRenderInstance::iterate(void)
699 {
700     tcu::TextureLevel resultImage;
701 
702     // log
703     if (m_firstIteration)
704     {
705         logTestPlan();
706         m_firstIteration = false;
707     }
708 
709     // render
710     {
711         // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
712         const vk::VkImageSubresourceRange fullSubrange = {
713             vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
714             0u,                            // baseMipLevel
715             1u,                            // mipLevels
716             0u,                            // baseArraySlice
717             1u,                            // arraySize
718         };
719         const vk::VkImageMemoryBarrier imageBarrier = {
720             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
721             nullptr,
722             0u,                                           // srcAccessMask
723             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,     // dstAccessMask
724             vk::VK_IMAGE_LAYOUT_UNDEFINED,                // oldLayout
725             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
726             VK_QUEUE_FAMILY_IGNORED,                      // srcQueueFamilyIndex
727             VK_QUEUE_FAMILY_IGNORED,                      // destQueueFamilyIndex
728             *m_colorAttachmentImage,                      // image
729             fullSubrange,                                 // subresourceRange
730         };
731 
732         const vk::Unique<vk::VkCommandBuffer> cmd(
733             vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
734 
735         beginCommandBuffer(m_vki, *cmd);
736         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
737                                  vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0, 0,
738                                  nullptr, 0, nullptr, 1, &imageBarrier);
739         endCommandBuffer(m_vki, *cmd);
740 
741         submitCommandsAndWait(m_vki, m_device, m_queue, cmd.get());
742 
743         renderToTarget();
744     }
745 
746     // read and verify
747     readRenderTarget(resultImage);
748 #ifdef CTS_USES_VULKANSC
749     // skip costly verification in main process
750     if (!m_context.getTestContext().getCommandLine().isSubProcess())
751         return tcu::TestStatus::pass("Success");
752 #endif // CTS_USES_VULKANSC
753     return verifyResultImage(resultImage.getAccess());
754 }
755 
756 class RenderInstanceShaders
757 {
758 public:
759     RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
760                           const vk::VkPhysicalDeviceFeatures &deviceFeatures,
761                           const vk::BinaryCollection &programCollection);
762 
hasTessellationStage(void) const763     inline bool hasTessellationStage(void) const
764     {
765         return *m_tessCtrlShaderModule != VK_NULL_HANDLE || *m_tessEvalShaderModule != VK_NULL_HANDLE;
766     }
getNumStages(void) const767     inline uint32_t getNumStages(void) const
768     {
769         return (uint32_t)m_stageInfos.size();
770     }
getStages(void) const771     inline const vk::VkPipelineShaderStageCreateInfo *getStages(void) const
772     {
773         return &m_stageInfos[0];
774     }
775 
776 private:
777     void addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
778                   const vk::VkPhysicalDeviceFeatures &deviceFeatures, const vk::BinaryCollection &programCollection,
779                   const char *name, vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule);
780 
781     vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
782                                                                  vk::VkShaderModule shader) const;
783 
784     vk::Move<vk::VkShaderModule> m_vertexShaderModule;
785     vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule;
786     vk::Move<vk::VkShaderModule> m_tessEvalShaderModule;
787     vk::Move<vk::VkShaderModule> m_geometryShaderModule;
788     vk::Move<vk::VkShaderModule> m_fragmentShaderModule;
789     std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos;
790 };
791 
RenderInstanceShaders(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::VkPhysicalDeviceFeatures & deviceFeatures,const vk::BinaryCollection & programCollection)792 RenderInstanceShaders::RenderInstanceShaders(const vk::DeviceInterface &vki, vk::VkDevice device,
793                                              const vk::VkPhysicalDeviceFeatures &deviceFeatures,
794                                              const vk::BinaryCollection &programCollection)
795 {
796     addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT,
797              &m_vertexShaderModule);
798     addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
799              &m_tessCtrlShaderModule);
800     addStage(vki, device, deviceFeatures, programCollection, "tess_eval",
801              vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule);
802     addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT,
803              &m_geometryShaderModule);
804     addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT,
805              &m_fragmentShaderModule);
806 
807     DE_ASSERT(!m_stageInfos.empty());
808 }
809 
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)810 void RenderInstanceShaders::addStage(const vk::DeviceInterface &vki, vk::VkDevice device,
811                                      const vk::VkPhysicalDeviceFeatures &deviceFeatures,
812                                      const vk::BinaryCollection &programCollection, const char *name,
813                                      vk::VkShaderStageFlagBits stage, vk::Move<vk::VkShaderModule> *outModule)
814 {
815     if (programCollection.contains(name))
816     {
817         if (vk::isShaderStageSupported(deviceFeatures, stage))
818         {
819             vk::Move<vk::VkShaderModule> module =
820                 createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
821 
822             m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module));
823             *outModule = module;
824         }
825         else
826         {
827             // Wait for the GPU to idle so that throwing the exception
828             // below doesn't free in-use GPU resource.
829             vki.deviceWaitIdle(device);
830             TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str());
831         }
832     }
833 }
834 
getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,vk::VkShaderModule shader) const835 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo(vk::VkShaderStageFlagBits stage,
836                                                                                     vk::VkShaderModule shader) const
837 {
838     const vk::VkPipelineShaderStageCreateInfo stageCreateInfo = {
839         vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
840         nullptr,
841         (vk::VkPipelineShaderStageCreateFlags)0,
842         stage,  // stage
843         shader, // shader
844         "main",
845         nullptr, // pSpecializationInfo
846     };
847     return stageCreateInfo;
848 }
849 
850 class SingleCmdRenderInstance : public SingleTargetRenderInstance
851 {
852 public:
853     SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize, const bool bind2);
854 
855 private:
856     vk::Move<vk::VkPipeline> createPipeline(vk::VkPipelineLayout pipelineLayout);
857 
858     virtual vk::VkPipelineLayout getPipelineLayout(void) const     = 0;
859     virtual void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const = 0;
860 
861     void renderToTarget(void);
862 
863     const bool m_isPrimaryCmdBuf;
864 };
865 
SingleCmdRenderInstance(Context & context,bool isPrimaryCmdBuf,const tcu::UVec2 & renderSize,const bool bind2)866 SingleCmdRenderInstance::SingleCmdRenderInstance(Context &context, bool isPrimaryCmdBuf, const tcu::UVec2 &renderSize,
867                                                  const bool bind2)
868     : SingleTargetRenderInstance(context, renderSize, bind2)
869     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
870 {
871 }
872 
createPipeline(vk::VkPipelineLayout pipelineLayout)873 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline(vk::VkPipelineLayout pipelineLayout)
874 {
875     const RenderInstanceShaders shaderStages(m_vki, m_device, m_context.getDeviceFeatures(),
876                                              m_context.getBinaryCollection());
877     const vk::VkPrimitiveTopology topology                          = shaderStages.hasTessellationStage() ?
878                                                                           vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
879                                                                           vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
880     const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
881         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
882         nullptr,
883         (vk::VkPipelineVertexInputStateCreateFlags)0,
884         0u,      // bindingCount
885         nullptr, // pVertexBindingDescriptions
886         0u,      // attributeCount
887         nullptr, // pVertexAttributeDescriptions
888     };
889     const vk::VkPipelineInputAssemblyStateCreateInfo iaState = {
890         vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
891         nullptr,
892         (vk::VkPipelineInputAssemblyStateCreateFlags)0,
893         topology, // topology
894         VK_FALSE, // primitiveRestartEnable
895     };
896     const vk::VkPipelineTessellationStateCreateInfo tessState = {
897         vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr,
898         (vk::VkPipelineTessellationStateCreateFlags)0,
899         3u, // patchControlPoints
900     };
901     const vk::VkViewport viewport                       = vk::makeViewport(m_targetSize);
902     const vk::VkRect2D renderArea                       = vk::makeRect2D(m_targetSize);
903     const vk::VkPipelineViewportStateCreateInfo vpState = {
904         vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
905         nullptr,
906         (vk::VkPipelineViewportStateCreateFlags)0,
907         1u, // viewportCount
908         &viewport,
909         1u,
910         &renderArea,
911     };
912     const vk::VkPipelineRasterizationStateCreateInfo rsState = {
913         vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
914         nullptr,
915         (vk::VkPipelineRasterizationStateCreateFlags)0,
916         VK_FALSE,                            // depthClipEnable
917         VK_FALSE,                            // rasterizerDiscardEnable
918         vk::VK_POLYGON_MODE_FILL,            // fillMode
919         vk::VK_CULL_MODE_NONE,               // cullMode
920         vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
921         VK_FALSE,                            // depthBiasEnable
922         0.0f,                                // depthBias
923         0.0f,                                // depthBiasClamp
924         0.0f,                                // slopeScaledDepthBias
925         1.0f,                                // lineWidth
926     };
927     const vk::VkSampleMask sampleMask                      = 0x01u;
928     const vk::VkPipelineMultisampleStateCreateInfo msState = {
929         vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
930         nullptr,
931         (vk::VkPipelineMultisampleStateCreateFlags)0,
932         vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples
933         VK_FALSE,                  // sampleShadingEnable
934         0.0f,                      // minSampleShading
935         &sampleMask,               // sampleMask
936         VK_FALSE,                  // alphaToCoverageEnable
937         VK_FALSE,                  // alphaToOneEnable
938     };
939     const vk::VkPipelineDepthStencilStateCreateInfo dsState = {
940         vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
941         nullptr,
942         (vk::VkPipelineDepthStencilStateCreateFlags)0,
943         VK_FALSE,                 // depthTestEnable
944         VK_FALSE,                 // depthWriteEnable
945         vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp
946         VK_FALSE,                 // depthBoundsTestEnable
947         VK_FALSE,                 // stencilTestEnable
948         {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
949          0u}, // front
950         {vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u,
951          0u},  // back
952         -1.0f, // minDepthBounds
953         +1.0f, // maxDepthBounds
954     };
955     const vk::VkPipelineColorBlendAttachmentState cbAttachment = {
956         VK_FALSE,                 // blendEnable
957         vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor
958         vk::VK_BLEND_FACTOR_ZERO, // destBlendColor
959         vk::VK_BLEND_OP_ADD,      // blendOpColor
960         vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha
961         vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha
962         vk::VK_BLEND_OP_ADD,      // blendOpAlpha
963         (vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT | vk::VK_COLOR_COMPONENT_B_BIT |
964          vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask
965     };
966     const vk::VkPipelineColorBlendStateCreateInfo cbState = {
967         vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
968         nullptr,
969         (vk::VkPipelineColorBlendStateCreateFlags)0,
970         VK_FALSE,                 // logicOpEnable
971         vk::VK_LOGIC_OP_CLEAR,    // logicOp
972         1u,                       // attachmentCount
973         &cbAttachment,            // pAttachments
974         {0.0f, 0.0f, 0.0f, 0.0f}, // blendConst
975     };
976     const vk::VkGraphicsPipelineCreateInfo createInfo = {
977         vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
978         nullptr,
979         (vk::VkPipelineCreateFlags)0,
980         shaderStages.getNumStages(),                                  // stageCount
981         shaderStages.getStages(),                                     // pStages
982         &vertexInputState,                                            // pVertexInputState
983         &iaState,                                                     // pInputAssemblyState
984         (shaderStages.hasTessellationStage() ? &tessState : nullptr), // pTessellationState
985         &vpState,                                                     // pViewportState
986         &rsState,                                                     // pRasterState
987         &msState,                                                     // pMultisampleState
988         &dsState,                                                     // pDepthStencilState
989         &cbState,                                                     // pColorBlendState
990         nullptr,                                                      // pDynamicState
991         pipelineLayout,                                               // layout
992         *m_renderPass,                                                // renderPass
993         0u,                                                           // subpass
994         VK_NULL_HANDLE,                                               // basePipelineHandle
995         0u,                                                           // basePipelineIndex
996     };
997     return createGraphicsPipeline(m_vki, m_device, VK_NULL_HANDLE, &createInfo);
998 }
999 
renderToTarget(void)1000 void SingleCmdRenderInstance::renderToTarget(void)
1001 {
1002     const vk::VkRect2D renderArea = {
1003         {0, 0},                               // offset
1004         {m_targetSize.x(), m_targetSize.y()}, // extent
1005     };
1006     const vk::VkCommandBufferInheritanceInfo passCmdBufInheritInfo = {
1007         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
1008         nullptr,
1009         (vk::VkRenderPass)*m_renderPass,   // renderPass
1010         0u,                                // subpass
1011         (vk::VkFramebuffer)*m_framebuffer, // framebuffer
1012         VK_FALSE,                          // occlusionQueryEnable
1013         (vk::VkQueryControlFlags)0,
1014         (vk::VkQueryPipelineStatisticFlags)0,
1015     };
1016     const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo = {
1017         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1018         nullptr,
1019         vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags
1020         &passCmdBufInheritInfo,
1021     };
1022 
1023     const vk::VkPipelineLayout pipelineLayout(getPipelineLayout());
1024     const vk::Unique<vk::VkPipeline> pipeline(createPipeline(pipelineLayout));
1025     const vk::Unique<vk::VkCommandBuffer> mainCmd(
1026         vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1027     const vk::Unique<vk::VkCommandBuffer> passCmd(
1028         (m_isPrimaryCmdBuf) ?
1029             (vk::Move<vk::VkCommandBuffer>()) :
1030             (vk::allocateCommandBuffer(m_vki, m_device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)));
1031     const vk::Unique<vk::VkFence> fence(vk::createFence(m_vki, m_device));
1032     const vk::VkSubpassContents passContents =
1033         (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1034 
1035     if (!m_isPrimaryCmdBuf)
1036     {
1037         VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1038         m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1039         writeDrawCmdBuffer(*passCmd);
1040         endCommandBuffer(m_vki, *passCmd);
1041     }
1042 
1043     beginCommandBuffer(m_vki, *mainCmd);
1044     beginRenderPass(m_vki, *mainCmd, *m_renderPass, *m_framebuffer, renderArea, tcu::Vec4(0.0f), passContents);
1045 
1046     if (m_isPrimaryCmdBuf)
1047     {
1048         m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1049         writeDrawCmdBuffer(*mainCmd);
1050     }
1051     else
1052     {
1053         m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1054     }
1055 
1056     endRenderPass(m_vki, *mainCmd);
1057     endCommandBuffer(m_vki, *mainCmd);
1058 
1059     // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1060     submitCommandsAndWait(m_vki, m_device, m_queue, mainCmd.get());
1061 }
1062 
1063 enum DescriptorSetCount
1064 {
1065     DESCRIPTOR_SET_COUNT_SINGLE = 0,             //!< single descriptor set
1066     DESCRIPTOR_SET_COUNT_MULTIPLE,               //!< multiple descriptor sets
1067     DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS, //!< multiple discontiguous descriptor sets
1068 
1069     DESCRIPTOR_SET_COUNT_LAST
1070 };
1071 
getDescriptorSetCount(DescriptorSetCount count)1072 uint32_t getDescriptorSetCount(DescriptorSetCount count)
1073 {
1074     switch (count)
1075     {
1076     case DESCRIPTOR_SET_COUNT_SINGLE:
1077         return 1u;
1078     case DESCRIPTOR_SET_COUNT_MULTIPLE:
1079     case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1080         return 2u;
1081     default:
1082         DE_FATAL("Impossible");
1083         return 0u;
1084     }
1085 }
1086 
getDescriptorSetNdx(DescriptorSetCount count,uint32_t setNdx)1087 uint32_t getDescriptorSetNdx(DescriptorSetCount count, uint32_t setNdx)
1088 {
1089     DE_ASSERT(setNdx < getDescriptorSetCount(count));
1090 
1091     const uint32_t contiguousNdx[]    = {0, 1};
1092     const uint32_t discontiguousNdx[] = {0, 2};
1093 
1094     switch (count)
1095     {
1096     case DESCRIPTOR_SET_COUNT_SINGLE:
1097         return 0u;
1098     case DESCRIPTOR_SET_COUNT_MULTIPLE:
1099         return contiguousNdx[setNdx];
1100     case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1101         return discontiguousNdx[setNdx];
1102     default:
1103         DE_FATAL("Impossible");
1104         return 0u;
1105     }
1106 }
1107 
1108 enum ShaderInputInterface
1109 {
1110     SHADER_INPUT_SINGLE_DESCRIPTOR = 0,              //!< one descriptor
1111     SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS,    //!< multiple descriptors with contiguous binding id's
1112     SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with discontiguous binding id's
1113     SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS,     //!< multiple descriptors with large gaps between binding id's
1114     SHADER_INPUT_DESCRIPTOR_ARRAY,                   //!< descriptor array
1115 
1116     SHADER_INPUT_LAST
1117 };
1118 
getInterfaceNumResources(ShaderInputInterface shaderInterface)1119 uint32_t getInterfaceNumResources(ShaderInputInterface shaderInterface)
1120 {
1121     switch (shaderInterface)
1122     {
1123     case SHADER_INPUT_SINGLE_DESCRIPTOR:
1124         return 1u;
1125     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1126         return 2u;
1127     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1128         return 2u;
1129     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1130         return 2u;
1131     case SHADER_INPUT_DESCRIPTOR_ARRAY:
1132         return 2u;
1133 
1134     default:
1135         DE_FATAL("Impossible");
1136         return 0u;
1137     }
1138 }
1139 
getArbitraryBindingIndex(uint32_t ndx)1140 uint32_t getArbitraryBindingIndex(uint32_t ndx)
1141 {
1142     DE_ASSERT(ndx < 2);
1143 
1144     // Binding decoration value can be any 32-bit unsigned integer value.
1145     // 0xFFFE is the largest binding value accepted by glslang
1146 
1147     const uint32_t bufferIndices[] = {
1148 #ifndef CTS_USES_VULKANSC
1149         0x7FFEu, 0xFFFEu
1150 #else
1151         // Use smaller values for VulkanSC since these can produce huge static memory allocations
1152         0x1FFu, 0x3FFu
1153 #endif
1154     };
1155 
1156     return bufferIndices[ndx];
1157 }
1158 
1159 typedef de::MovePtr<vk::Allocation> AllocationMp;
1160 typedef de::SharedPtr<vk::Allocation> AllocationSp;
1161 typedef vk::Unique<vk::VkBuffer> BufferHandleUp;
1162 typedef de::SharedPtr<BufferHandleUp> BufferHandleSp;
1163 typedef vk::Unique<vk::VkBufferView> BufferViewHandleUp;
1164 typedef de::SharedPtr<BufferViewHandleUp> BufferViewHandleSp;
1165 typedef vk::Unique<vk::VkSampler> SamplerHandleUp;
1166 typedef de::SharedPtr<SamplerHandleUp> SamplerHandleSp;
1167 typedef vk::Unique<vk::VkImage> ImageHandleUp;
1168 typedef de::SharedPtr<ImageHandleUp> ImageHandleSp;
1169 typedef vk::Unique<vk::VkImageView> ImageViewHandleUp;
1170 typedef de::SharedPtr<ImageViewHandleUp> ImageViewHandleSp;
1171 typedef vk::Unique<vk::VkDescriptorSet> DescriptorSetHandleUp;
1172 typedef de::SharedPtr<DescriptorSetHandleUp> DescriptorSetHandleSp;
1173 typedef vk::Unique<vk::VkDescriptorSetLayout> DescriptorSetLayoutHandleUp;
1174 typedef de::SharedPtr<DescriptorSetLayoutHandleUp> DescriptorSetLayoutHandleSp;
1175 #ifndef CTS_USES_VULKANSC
1176 typedef vk::Unique<vk::VkDescriptorUpdateTemplate> UpdateTemplateHandleUp;
1177 typedef de::SharedPtr<UpdateTemplateHandleUp> UpdateTemplateHandleSp;
1178 #endif
1179 
1180 class BufferRenderInstance : public SingleCmdRenderInstance
1181 {
1182 public:
1183     BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1184                          vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1185                          vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1186                          ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1187                          bool dynamicOffsetNonZero, bool bind2);
1188 
1189     static std::vector<uint32_t> getViewOffsets(DescriptorSetCount descriptorSetCount,
1190                                                 ShaderInputInterface shaderInterface, bool setViewOffset);
1191 
1192     static std::vector<uint32_t> getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1193                                                    ShaderInputInterface shaderInterface, bool dynamicOffsetNonZero);
1194 
1195     static std::vector<BufferHandleSp> createSourceBuffers(
1196         const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator,
1197         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1198         ShaderInputInterface shaderInterface, const std::vector<uint32_t> &viewOffset,
1199         const std::vector<uint32_t> &dynamicOffset, std::vector<AllocationSp> &bufferMemory);
1200 
1201     static vk::Move<vk::VkBuffer> createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1202                                                      vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1203                                                      uint32_t setNdx, uint32_t offset, uint32_t bufferSize,
1204                                                      de::MovePtr<vk::Allocation> *outMemory);
1205 
1206     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
1207                                                                vk::VkDescriptorType descriptorType,
1208                                                                DescriptorSetCount descriptorSetCount,
1209                                                                ShaderInputInterface shaderInterface);
1210 
1211     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
1212         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1213         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1214         DescriptorUpdateMethod updateMethod);
1215 
1216     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
1217         const vk::DeviceInterface &vki, vk::VkDevice device,
1218         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
1219 
1220     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
1221         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1222         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1223         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1224         ShaderInputInterface shaderInterface, const std::vector<BufferHandleSp> &buffers,
1225         const std::vector<uint32_t> &offsets, vk::DescriptorSetUpdateBuilder &updateBuilder,
1226         std::vector<uint32_t> &descriptorsPerSet,
1227 #ifndef CTS_USES_VULKANSC
1228         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1229 #endif
1230         vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
1231 
1232     static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1233                                    vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1234                                    vk::VkBuffer sourceBufferA, const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1235                                    const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1236                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
1237                                    std::vector<uint32_t> &descriptorsPerSet,
1238                                    DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
1239 
1240 #ifndef CTS_USES_VULKANSC
1241     static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
1242                                                vk::VkDescriptorSetLayout descriptorSetLayout, uint32_t setNdx,
1243                                                vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType,
1244                                                ShaderInputInterface shaderInterface, vk::VkBuffer sourceBufferA,
1245                                                const uint32_t viewOffsetA, vk::VkBuffer sourceBufferB,
1246                                                const uint32_t viewOffsetB, vk::VkDescriptorSet descriptorSet,
1247                                                std::vector<UpdateTemplateHandleSp> &updateTemplates,
1248                                                std::vector<RawUpdateRegistry> &registry, bool withPush = false,
1249                                                vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
1250 #endif
1251 
1252     void logTestPlan(void) const;
1253     vk::VkPipelineLayout getPipelineLayout(void) const;
1254     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
1255     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
1256 
1257     enum
1258     {
1259         RENDER_SIZE      = 128,
1260         BUFFER_DATA_SIZE = 8 * sizeof(float),
1261         BUFFER_SIZE_A    = 2048, //!< a lot more than required
1262         BUFFER_SIZE_B    = 2560, //!< a lot more than required
1263         BUFFER_SIZE_C    = 2128, //!< a lot more than required
1264         BUFFER_SIZE_D    = 2136, //!< a lot more than required
1265 
1266         STATIC_OFFSET_VALUE_A  = 256,
1267         DYNAMIC_OFFSET_VALUE_A = 512,
1268         STATIC_OFFSET_VALUE_B  = 1024,
1269         DYNAMIC_OFFSET_VALUE_B = 768,
1270         STATIC_OFFSET_VALUE_C  = 512,
1271         DYNAMIC_OFFSET_VALUE_C = 512,
1272         STATIC_OFFSET_VALUE_D  = 768,
1273         DYNAMIC_OFFSET_VALUE_D = 1024,
1274     };
1275 
1276     const DescriptorUpdateMethod m_updateMethod;
1277     const vk::VkDescriptorType m_descriptorType;
1278     const DescriptorSetCount m_descriptorSetCount;
1279     const ShaderInputInterface m_shaderInterface;
1280     const bool m_setViewOffset;
1281     const bool m_setDynamicOffset;
1282     const bool m_dynamicOffsetNonZero;
1283     const vk::VkShaderStageFlags m_stageFlags;
1284     const vk::VkShaderStageFlags m_existingStages;
1285 
1286     const std::vector<uint32_t> m_viewOffset;
1287     const std::vector<uint32_t> m_dynamicOffset;
1288 
1289     std::vector<AllocationSp> m_bufferMemory;
1290     const std::vector<BufferHandleSp> m_sourceBuffer;
1291     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
1292 #ifndef CTS_USES_VULKANSC
1293     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
1294     std::vector<RawUpdateRegistry> m_updateRegistry;
1295 #endif
1296     vk::DescriptorSetUpdateBuilder m_updateBuilder;
1297     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
1298     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
1299     std::vector<uint32_t> m_descriptorsPerSet;
1300     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
1301 };
1302 
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)1303 BufferRenderInstance::BufferRenderInstance(Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
1304                                            vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
1305                                            vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
1306                                            ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
1307                                            bool dynamicOffsetNonZero, bool bind2)
1308     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
1309     , m_updateMethod(updateMethod)
1310     , m_descriptorType(descriptorType)
1311     , m_descriptorSetCount(descriptorSetCount)
1312     , m_shaderInterface(shaderInterface)
1313     , m_setViewOffset(viewOffset)
1314     , m_setDynamicOffset(dynamicOffset)
1315     , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
1316     , m_stageFlags(stageFlags)
1317     , m_existingStages(existingStages)
1318     , m_viewOffset(getViewOffsets(m_descriptorSetCount, m_shaderInterface, m_setViewOffset))
1319     , m_dynamicOffset(getDynamicOffsets(m_descriptorSetCount, m_shaderInterface, m_dynamicOffsetNonZero))
1320     , m_bufferMemory()
1321     , m_sourceBuffer(createSourceBuffers(m_vki, m_device, m_allocator, m_descriptorType, m_descriptorSetCount,
1322                                          m_shaderInterface, m_viewOffset, m_dynamicOffset, m_bufferMemory))
1323     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
1324 #ifndef CTS_USES_VULKANSC
1325     , m_updateTemplates()
1326     , m_updateRegistry()
1327 #endif
1328     , m_updateBuilder()
1329     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
1330                                                         m_shaderInterface, m_stageFlags, m_updateMethod))
1331     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
1332     , m_descriptorsPerSet()
1333     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorSetLayouts, *m_descriptorPool,
1334                                             m_descriptorType, m_descriptorSetCount, m_shaderInterface, m_sourceBuffer,
1335                                             m_viewOffset, m_updateBuilder, m_descriptorsPerSet,
1336 #ifndef CTS_USES_VULKANSC
1337                                             m_updateTemplates, m_updateRegistry,
1338 #endif
1339                                             *m_pipelineLayout))
1340 {
1341     if (m_setDynamicOffset)
1342         DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1343     if (m_dynamicOffsetNonZero)
1344         DE_ASSERT(m_setDynamicOffset);
1345 }
1346 
getViewOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool setViewOffset)1347 std::vector<uint32_t> BufferRenderInstance::getViewOffsets(DescriptorSetCount descriptorSetCount,
1348                                                            ShaderInputInterface shaderInterface, bool setViewOffset)
1349 {
1350     const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1351     std::vector<uint32_t> viewOffset;
1352 
1353     for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1354     {
1355         const uint32_t staticOffsetValues[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B, STATIC_OFFSET_VALUE_C,
1356                                                STATIC_OFFSET_VALUE_D};
1357 
1358         viewOffset.push_back(
1359             setViewOffset ? (staticOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1360     }
1361 
1362     return viewOffset;
1363 }
1364 
getDynamicOffsets(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool dynamicOffsetNonZero)1365 std::vector<uint32_t> BufferRenderInstance::getDynamicOffsets(DescriptorSetCount descriptorSetCount,
1366                                                               ShaderInputInterface shaderInterface,
1367                                                               bool dynamicOffsetNonZero)
1368 {
1369     const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1370     std::vector<uint32_t> dynamicOffset;
1371 
1372     for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1373     {
1374         const uint32_t dynamicOffsetValues[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B, DYNAMIC_OFFSET_VALUE_C,
1375                                                 DYNAMIC_OFFSET_VALUE_D};
1376 
1377         dynamicOffset.push_back(
1378             dynamicOffsetNonZero ? (dynamicOffsetValues[bufferNdx % getInterfaceNumResources(shaderInterface)]) : (0u));
1379     }
1380 
1381     return dynamicOffset;
1382 }
1383 
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)1384 std::vector<BufferHandleSp> BufferRenderInstance::createSourceBuffers(
1385     const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
1386     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1387     const std::vector<uint32_t> &viewOffset, const std::vector<uint32_t> &dynamicOffset,
1388     std::vector<AllocationSp> &bufferMemory)
1389 {
1390     const int numBuffers = getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
1391     std::vector<uint32_t> effectiveOffset;
1392     std::vector<uint32_t> bufferSize;
1393     std::vector<BufferHandleSp> sourceBuffers;
1394 
1395     for (int bufferNdx = 0; bufferNdx < numBuffers; bufferNdx++)
1396     {
1397         const uint32_t bufferSizeValues[] = {BUFFER_SIZE_A, BUFFER_SIZE_B, BUFFER_SIZE_C, BUFFER_SIZE_D};
1398 
1399         effectiveOffset.push_back(isDynamicDescriptorType(descriptorType) ?
1400                                       (viewOffset[bufferNdx] + dynamicOffset[bufferNdx]) :
1401                                       (viewOffset[bufferNdx]));
1402         bufferSize.push_back(bufferSizeValues[bufferNdx % getInterfaceNumResources(shaderInterface)]);
1403     }
1404 
1405     // Create source buffers
1406     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1407     {
1408         for (uint32_t bufferNdx = 0; bufferNdx < getInterfaceNumResources(shaderInterface); bufferNdx++)
1409         {
1410             de::MovePtr<vk::Allocation> memory;
1411             vk::Move<vk::VkBuffer> buffer =
1412                 createSourceBuffer(vki, device, allocator, descriptorType, setNdx, effectiveOffset[bufferNdx],
1413                                    bufferSize[bufferNdx], &memory);
1414 
1415             bufferMemory.push_back(AllocationSp(memory.release()));
1416             sourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
1417         }
1418     }
1419 
1420     return sourceBuffers;
1421 }
1422 
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)1423 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1424                                                                 vk::Allocator &allocator,
1425                                                                 vk::VkDescriptorType descriptorType, uint32_t setNdx,
1426                                                                 uint32_t offset, uint32_t bufferSize,
1427                                                                 de::MovePtr<vk::Allocation> *outMemory)
1428 {
1429     static const float s_colors[] = {
1430         0.0f, 1.0f, 0.0f, 1.0f, // green
1431         1.0f, 1.0f, 0.0f, 1.0f, // yellow
1432         0.0f, 0.0f, 1.0f, 1.0f, // blue
1433         1.0f, 0.0f, 0.0f, 1.0f  // red
1434     };
1435     DE_STATIC_ASSERT(sizeof(s_colors) / 2 == BUFFER_DATA_SIZE);
1436     DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1437     DE_ASSERT(offset % sizeof(float) == 0);
1438     DE_ASSERT(bufferSize % sizeof(float) == 0);
1439 
1440     const bool isUniformBuffer = isUniformDescriptorType(descriptorType);
1441     const vk::VkBufferUsageFlags usageFlags =
1442         (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1443     const float preGuardValue                     = 0.5f;
1444     const float postGuardValue                    = 0.75f;
1445     const vk::VkBufferCreateInfo bufferCreateInfo = {
1446         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1447         nullptr,
1448         0u,                            // flags
1449         bufferSize,                    // size
1450         usageFlags,                    // usage
1451         vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1452         0u,                            // queueFamilyCount
1453         nullptr,                       // pQueueFamilyIndices
1454     };
1455     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &bufferCreateInfo));
1456     de::MovePtr<vk::Allocation> bufferMemory =
1457         allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1458     void *const mapPtr = bufferMemory->getHostPtr();
1459 
1460     // guard with interesting values
1461     for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1462         deMemcpy((uint8_t *)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1463 
1464     deMemcpy((uint8_t *)mapPtr + offset, &s_colors[8 * (setNdx % 2)], sizeof(s_colors) / 2);
1465     for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors) / 2;
1466          postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1467         deMemcpy((uint8_t *)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1468     deMemset((uint8_t *)mapPtr + offset + sizeof(s_colors) / 2, 0x5A,
1469              (size_t)bufferSize - (size_t)offset -
1470                  sizeof(s_colors) / 2); // fill with interesting pattern that produces valid floats
1471 
1472     flushAlloc(vki, device, *bufferMemory);
1473 
1474     // Flushed host-visible memory is automatically made available to the GPU, no barrier is needed.
1475 
1476     *outMemory = bufferMemory;
1477     return buffer;
1478 }
1479 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)1480 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
1481                                                                           vk::VkDevice device,
1482                                                                           vk::VkDescriptorType descriptorType,
1483                                                                           DescriptorSetCount descriptorSetCount,
1484                                                                           ShaderInputInterface shaderInterface)
1485 {
1486     return vk::DescriptorPoolBuilder()
1487         .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
1488         .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1489                getDescriptorSetCount(descriptorSetCount));
1490 }
1491 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)1492 std::vector<DescriptorSetLayoutHandleSp> BufferRenderInstance::createDescriptorSetLayouts(
1493     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
1494     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
1495     DescriptorUpdateMethod updateMethod)
1496 {
1497 #ifdef CTS_USES_VULKANSC
1498     DE_UNREF(updateMethod);
1499 #endif
1500     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
1501 
1502 #ifndef CTS_USES_VULKANSC
1503     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
1504         updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1505     {
1506         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
1507     }
1508 #endif
1509 
1510     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
1511 
1512     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1513     {
1514         vk::DescriptorSetLayoutBuilder builder;
1515         switch (shaderInterface)
1516         {
1517         case SHADER_INPUT_SINGLE_DESCRIPTOR:
1518             builder.addSingleBinding(descriptorType, stageFlags);
1519             break;
1520 
1521         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1522             builder.addSingleBinding(descriptorType, stageFlags);
1523             builder.addSingleBinding(descriptorType, stageFlags);
1524             break;
1525 
1526         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1527             builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
1528             builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
1529             break;
1530 
1531         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1532             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
1533             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
1534             break;
1535 
1536         case SHADER_INPUT_DESCRIPTOR_ARRAY:
1537             builder.addArrayBinding(descriptorType, 2u, stageFlags);
1538             break;
1539 
1540         default:
1541             DE_FATAL("Impossible");
1542         }
1543 
1544         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
1545         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
1546 
1547         // Add an empty descriptor set layout between sets 0 and 2
1548         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
1549         {
1550             vk::DescriptorSetLayoutBuilder emptyBuilder;
1551             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
1552                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
1553             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
1554         }
1555     }
1556     return descriptorSetLayouts;
1557 }
1558 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)1559 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout(
1560     const vk::DeviceInterface &vki, vk::VkDevice device,
1561     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
1562 {
1563     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
1564     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
1565         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
1566 
1567     const vk::VkPipelineLayoutCreateInfo createInfo = {
1568         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1569         nullptr,
1570         (vk::VkPipelineLayoutCreateFlags)0,
1571         (uint32_t)layoutHandles.size(), // descriptorSetCount
1572         &layoutHandles.front(),         // pSetLayouts
1573         0u,                             // pushConstantRangeCount
1574         nullptr,                        // pPushConstantRanges
1575     };
1576     return vk::createPipelineLayout(vki, device, &createInfo);
1577 }
1578 
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)1579 std::vector<DescriptorSetHandleSp> BufferRenderInstance::createDescriptorSets(
1580     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
1581     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool descriptorPool,
1582     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
1583     const std::vector<BufferHandleSp> &buffers, const std::vector<uint32_t> &offsets,
1584     vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
1585 #ifndef CTS_USES_VULKANSC
1586     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
1587 #endif
1588     vk::VkPipelineLayout pipelineLayout)
1589 {
1590 #ifdef CTS_USES_VULKANSC
1591     DE_UNREF(pipelineLayout);
1592 #endif
1593     std::vector<DescriptorSetHandleSp> descriptorSets;
1594 
1595     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
1596     {
1597         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
1598         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
1599                                                            descriptorPool, 1u, &layout};
1600 
1601         vk::VkBuffer bufferA = **buffers[(setNdx * getInterfaceNumResources(shaderInterface)) % buffers.size()];
1602         vk::VkBuffer bufferB = **buffers[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % buffers.size()];
1603         uint32_t offsetA     = offsets[(setNdx * getInterfaceNumResources(shaderInterface)) % offsets.size()];
1604         uint32_t offsetB     = offsets[(setNdx * getInterfaceNumResources(shaderInterface) + 1) % offsets.size()];
1605 
1606         vk::Move<vk::VkDescriptorSet> descriptorSet;
1607 
1608         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
1609             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1610         {
1611             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
1612         }
1613         else
1614         {
1615             descriptorSet = vk::Move<vk::VkDescriptorSet>();
1616         }
1617 
1618 #ifndef CTS_USES_VULKANSC
1619         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
1620         {
1621             writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1622                                            bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1623                                            updateRegistry);
1624         }
1625         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1626         {
1627             writeDescriptorSetWithTemplate(vki, device, layout, setNdx, descriptorPool, descriptorType, shaderInterface,
1628                                            bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplates,
1629                                            updateRegistry, true, pipelineLayout);
1630         }
1631         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1632         {
1633             writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1634                                *descriptorSet, updateBuilder, descriptorsPerSet, updateMethod);
1635         }
1636         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1637 #endif
1638         {
1639             writeDescriptorSet(vki, device, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB,
1640                                *descriptorSet, updateBuilder, descriptorsPerSet);
1641         }
1642 
1643         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
1644     }
1645     return descriptorSets;
1646 }
1647 
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)1648 void BufferRenderInstance::writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
1649                                               vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1650                                               vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB,
1651                                               const uint32_t offsetB, vk::VkDescriptorSet descriptorSet,
1652                                               vk::DescriptorSetUpdateBuilder &updateBuilder,
1653                                               std::vector<uint32_t> &descriptorsPerSet,
1654                                               DescriptorUpdateMethod updateMethod)
1655 {
1656     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1657         vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1658         vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1659     };
1660     uint32_t numDescriptors = 0u;
1661 
1662     switch (shaderInterface)
1663     {
1664     case SHADER_INPUT_SINGLE_DESCRIPTOR:
1665         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1666                                   &bufferInfos[0]);
1667         numDescriptors++;
1668         break;
1669 
1670     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1671         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1672                                   &bufferInfos[0]);
1673         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
1674                                   &bufferInfos[1]);
1675         numDescriptors += 2;
1676         break;
1677 
1678     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1679         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1680                                   &bufferInfos[0]);
1681         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
1682                                   &bufferInfos[1]);
1683         numDescriptors += 2;
1684         break;
1685 
1686     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1687         updateBuilder.writeSingle(descriptorSet,
1688                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
1689                                   descriptorType, &bufferInfos[0]);
1690         updateBuilder.writeSingle(descriptorSet,
1691                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
1692                                   descriptorType, &bufferInfos[1]);
1693         numDescriptors += 2;
1694         break;
1695 
1696     case SHADER_INPUT_DESCRIPTOR_ARRAY:
1697         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
1698                                  2u, bufferInfos);
1699         numDescriptors++;
1700         break;
1701 
1702     default:
1703         DE_FATAL("Impossible");
1704     }
1705 
1706     descriptorsPerSet.push_back(numDescriptors);
1707 
1708     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
1709     {
1710         updateBuilder.update(vki, device);
1711         updateBuilder.clear();
1712     }
1713 }
1714 
1715 #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)1716 void BufferRenderInstance::writeDescriptorSetWithTemplate(
1717     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorSetLayout layout, uint32_t setNdx,
1718     vk::VkDescriptorPool descriptorPool, vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
1719     vk::VkBuffer bufferA, const uint32_t offsetA, vk::VkBuffer bufferB, const uint32_t offsetB,
1720     vk::VkDescriptorSet descriptorSet, std::vector<UpdateTemplateHandleSp> &updateTemplates,
1721     std::vector<RawUpdateRegistry> &registry, bool withPush, vk::VkPipelineLayout pipelineLayout)
1722 {
1723     DE_UNREF(descriptorPool);
1724     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
1725         vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1726         vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1727     };
1728     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
1729     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
1730         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
1731         nullptr,
1732         0,
1733         0,       // descriptorUpdateEntryCount
1734         nullptr, // pDescriptorUpdateEntries
1735         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
1736                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
1737         layout,
1738         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1739         pipelineLayout,
1740         setNdx};
1741 
1742     RawUpdateRegistry updateRegistry;
1743 
1744     updateRegistry.addWriteObject(bufferInfos[0]);
1745     updateRegistry.addWriteObject(bufferInfos[1]);
1746 
1747     switch (shaderInterface)
1748     {
1749     case SHADER_INPUT_SINGLE_DESCRIPTOR:
1750         updateEntries.push_back(
1751             createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1752         break;
1753 
1754     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
1755         updateEntries.push_back(
1756             createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1757         updateEntries.push_back(
1758             createTemplateBinding(1u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1759         break;
1760 
1761     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
1762         updateEntries.push_back(
1763             createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
1764         updateEntries.push_back(
1765             createTemplateBinding(2u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
1766         break;
1767 
1768     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
1769         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
1770                                                       updateRegistry.getWriteObjectOffset(0), 0));
1771         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
1772                                                       updateRegistry.getWriteObjectOffset(1), 0));
1773         break;
1774 
1775     case SHADER_INPUT_DESCRIPTOR_ARRAY:
1776         updateEntries.push_back(createTemplateBinding(0u, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
1777                                                       sizeof(bufferInfos[0])));
1778         break;
1779 
1780     default:
1781         DE_FATAL("Impossible");
1782     }
1783 
1784     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
1785     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
1786 
1787     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
1788         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
1789     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
1790     registry.push_back(updateRegistry);
1791 
1792     if (!withPush)
1793     {
1794         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
1795                                             registry.back().getRawPointer());
1796     }
1797 }
1798 #endif
1799 
logTestPlan(void) const1800 void BufferRenderInstance::logTestPlan(void) const
1801 {
1802     std::ostringstream msg;
1803 
1804     msg << "Rendering 2x2 yellow-green grid.\n"
1805         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
1806                                                                     "Multiple descriptor sets. ")
1807         << "Each descriptor set contains "
1808         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
1809             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
1810             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
1811             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
1812             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
1813                                                                                      nullptr)
1814         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1815         << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1816 
1817     if (isDynamicDescriptorType(m_descriptorType))
1818     {
1819         if (m_setDynamicOffset)
1820         {
1821             msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1822                 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1823         }
1824         else
1825         {
1826             msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1827         }
1828     }
1829 
1830     if (m_stageFlags == 0u)
1831     {
1832         msg << "Descriptors are not accessed in any shader stage.\n";
1833     }
1834     else
1835     {
1836         msg << "Descriptors are accessed in {"
1837             << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
1838             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
1839             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
1840             << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
1841             << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.\n";
1842     }
1843 
1844     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
1845 }
1846 
getPipelineLayout(void) const1847 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout(void) const
1848 {
1849     return *m_pipelineLayout;
1850 }
1851 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const1852 void BufferRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
1853 {
1854     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
1855         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1856     {
1857         std::vector<vk::VkDescriptorSet> sets;
1858         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1859             sets.push_back(**m_descriptorSets[setNdx]);
1860 
1861         switch (m_descriptorSetCount)
1862         {
1863         case DESCRIPTOR_SET_COUNT_SINGLE:
1864         case DESCRIPTOR_SET_COUNT_MULTIPLE:
1865         {
1866             // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1867             const uint32_t numOffsets              = (!m_setDynamicOffset) ? (0u) : ((uint32_t)m_dynamicOffset.size());
1868             const uint32_t *const dynamicOffsetPtr = (!m_setDynamicOffset) ? (nullptr) : (&m_dynamicOffset.front());
1869 
1870             bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1871                                getPipelineLayout(), 0, (int)sets.size(), &sets.front(), numOffsets, dynamicOffsetPtr,
1872                                m_bind2);
1873             break;
1874         }
1875         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
1876         {
1877             uint32_t dynamicOffsetNdx = 0u;
1878 
1879             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1880             {
1881                 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1882                 const uint32_t numOffsets =
1883                     (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1884                 const uint32_t *const dynamicOffsetPtr =
1885                     (!m_setDynamicOffset) ? (nullptr) : (&m_dynamicOffset[dynamicOffsetNdx]);
1886                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
1887 
1888                 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
1889                                    getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], numOffsets,
1890                                    dynamicOffsetPtr, m_bind2);
1891 
1892                 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
1893             }
1894             break;
1895         }
1896         default:
1897             DE_FATAL("Impossible");
1898         }
1899     }
1900 #ifndef CTS_USES_VULKANSC
1901     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
1902     {
1903         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1904             m_vki.cmdPushDescriptorSetWithTemplate(cmd, **m_updateTemplates[setNdx], getPipelineLayout(), setNdx,
1905                                                    (const void *)m_updateRegistry[setNdx].getRawPointer());
1906     }
1907     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
1908     {
1909         uint32_t descriptorNdx = 0u;
1910         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
1911         {
1912             const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
1913             m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, setNdx,
1914                                            descriptorNdx, numDescriptors);
1915             descriptorNdx += numDescriptors;
1916         }
1917     }
1918 #endif
1919 
1920     m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1921 }
1922 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const1923 tcu::TestStatus BufferRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
1924 {
1925     const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
1926     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
1927     const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
1928     tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
1929 
1930     tcu::Vec4 sample0 = tcu::Vec4(0.0f);
1931     tcu::Vec4 sample1 = tcu::Vec4(0.0f);
1932 
1933     if (m_stageFlags)
1934     {
1935         const tcu::Vec4 colors[] = {
1936             tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
1937             tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
1938             tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
1939             tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
1940         };
1941 
1942         for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
1943         {
1944             sample0 += colors[2 * (setNdx % 2)];
1945             sample1 += colors[2 * (setNdx % 2) + 1];
1946         }
1947 
1948         if (numDescriptorSets > 1)
1949         {
1950             sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
1951             sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
1952         }
1953     }
1954     else
1955     {
1956         sample0 = green;
1957         sample1 = yellow;
1958     }
1959 
1960     drawQuadrantReferenceResult(reference.getAccess(), sample1, sample0, sample0, sample1);
1961 
1962     if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
1963                          result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1964         return tcu::TestStatus::fail("Image verification failed");
1965     else
1966         return tcu::TestStatus::pass("Pass");
1967 }
1968 
1969 class ComputeInstanceResultBuffer
1970 {
1971 public:
1972     enum
1973     {
1974         DATA_SIZE = sizeof(tcu::Vec4[4])
1975     };
1976 
1977     ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device, vk::Allocator &allocator);
1978 
1979     void readResultContentsTo(tcu::Vec4 (*results)[4]) const;
1980 
getBuffer(void) const1981     inline vk::VkBuffer getBuffer(void) const
1982     {
1983         return *m_buffer;
1984     }
getResultReadBarrier(void) const1985     inline const vk::VkBufferMemoryBarrier *getResultReadBarrier(void) const
1986     {
1987         return &m_bufferBarrier;
1988     }
1989 
1990 private:
1991     static vk::Move<vk::VkBuffer> createResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
1992                                                      vk::Allocator &allocator,
1993                                                      de::MovePtr<vk::Allocation> *outAllocation);
1994 
1995     static vk::VkBufferMemoryBarrier createResultBufferBarrier(vk::VkBuffer buffer);
1996 
1997     const vk::DeviceInterface &m_vki;
1998     const vk::VkDevice m_device;
1999 
2000     de::MovePtr<vk::Allocation> m_bufferMem;
2001     const vk::Unique<vk::VkBuffer> m_buffer;
2002     const vk::VkBufferMemoryBarrier m_bufferBarrier;
2003 };
2004 
ComputeInstanceResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator)2005 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer(const vk::DeviceInterface &vki, vk::VkDevice device,
2006                                                          vk::Allocator &allocator)
2007     : m_vki(vki)
2008     , m_device(device)
2009     , m_bufferMem(nullptr)
2010     , m_buffer(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
2011     , m_bufferBarrier(createResultBufferBarrier(*m_buffer))
2012 {
2013 }
2014 
readResultContentsTo(tcu::Vec4 (* results)[4]) const2015 void ComputeInstanceResultBuffer::readResultContentsTo(tcu::Vec4 (*results)[4]) const
2016 {
2017     invalidateAlloc(m_vki, m_device, *m_bufferMem);
2018     deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
2019 }
2020 
createResultBuffer(const vk::DeviceInterface & vki,vk::VkDevice device,vk::Allocator & allocator,de::MovePtr<vk::Allocation> * outAllocation)2021 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer(const vk::DeviceInterface &vki,
2022                                                                        vk::VkDevice device, vk::Allocator &allocator,
2023                                                                        de::MovePtr<vk::Allocation> *outAllocation)
2024 {
2025     const vk::VkBufferCreateInfo createInfo = {
2026         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2027         nullptr,
2028         0u,                                     // flags
2029         (vk::VkDeviceSize)DATA_SIZE,            // size
2030         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
2031         vk::VK_SHARING_MODE_EXCLUSIVE,          // sharingMode
2032         0u,                                     // queueFamilyCount
2033         nullptr,                                // pQueueFamilyIndices
2034     };
2035     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(vki, device, &createInfo));
2036     de::MovePtr<vk::Allocation> allocation(
2037         allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
2038     const float clearValue = -1.0f;
2039     void *mapPtr           = allocation->getHostPtr();
2040 
2041     for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
2042         deMemcpy(((uint8_t *)mapPtr) + offset, &clearValue, sizeof(float));
2043 
2044     flushAlloc(vki, device, *allocation);
2045 
2046     *outAllocation = allocation;
2047     return buffer;
2048 }
2049 
createResultBufferBarrier(vk::VkBuffer buffer)2050 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier(vk::VkBuffer buffer)
2051 {
2052     const vk::VkBufferMemoryBarrier bufferBarrier = {
2053         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2054         nullptr,
2055         vk::VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
2056         vk::VK_ACCESS_HOST_READ_BIT,    // dstAccessMask
2057         VK_QUEUE_FAMILY_IGNORED,        // srcQueueFamilyIndex
2058         VK_QUEUE_FAMILY_IGNORED,        // destQueueFamilyIndex
2059         buffer,                         // buffer
2060         (vk::VkDeviceSize)0u,           // offset
2061         DATA_SIZE,                      // size
2062     };
2063     return bufferBarrier;
2064 }
2065 
2066 class ComputePipeline
2067 {
2068 public:
2069     ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device, const vk::BinaryCollection &programCollection,
2070                     uint32_t numDescriptorSets, const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2071 
getPipeline(void) const2072     inline vk::VkPipeline getPipeline(void) const
2073     {
2074         return *m_pipeline;
2075     }
getPipelineLayout(void) const2076     inline vk::VkPipelineLayout getPipelineLayout(void) const
2077     {
2078         return *m_pipelineLayout;
2079     }
2080 
2081 private:
2082     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(const vk::DeviceInterface &vki, vk::VkDevice device,
2083                                                                uint32_t numDescriptorSets,
2084                                                                const vk::VkDescriptorSetLayout *descriptorSetLayouts);
2085 
2086     static vk::Move<vk::VkPipeline> createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2087                                                    const vk::BinaryCollection &programCollection,
2088                                                    vk::VkPipelineLayout layout);
2089 
2090     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
2091     const vk::Unique<vk::VkPipeline> m_pipeline;
2092 };
2093 
ComputePipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2094 ComputePipeline::ComputePipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2095                                  const vk::BinaryCollection &programCollection, uint32_t numDescriptorSets,
2096                                  const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2097     : m_pipelineLayout(createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
2098     , m_pipeline(createPipeline(vki, device, programCollection, *m_pipelineLayout))
2099 {
2100 }
2101 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,uint32_t numDescriptorSets,const vk::VkDescriptorSetLayout * descriptorSetLayouts)2102 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout(
2103     const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t numDescriptorSets,
2104     const vk::VkDescriptorSetLayout *descriptorSetLayouts)
2105 {
2106     const vk::VkPipelineLayoutCreateInfo createInfo = {
2107         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2108         nullptr,
2109         (vk::VkPipelineLayoutCreateFlags)0,
2110         numDescriptorSets,    // descriptorSetCount
2111         descriptorSetLayouts, // pSetLayouts
2112         0u,                   // pushConstantRangeCount
2113         nullptr,              // pPushConstantRanges
2114     };
2115     return vk::createPipelineLayout(vki, device, &createInfo);
2116 }
2117 
createPipeline(const vk::DeviceInterface & vki,vk::VkDevice device,const vk::BinaryCollection & programCollection,vk::VkPipelineLayout layout)2118 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline(const vk::DeviceInterface &vki, vk::VkDevice device,
2119                                                          const vk::BinaryCollection &programCollection,
2120                                                          vk::VkPipelineLayout layout)
2121 {
2122     const vk::Unique<vk::VkShaderModule> computeModule(
2123         vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
2124     const vk::VkPipelineShaderStageCreateInfo cs = {
2125         vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2126         nullptr,
2127         (vk::VkPipelineShaderStageCreateFlags)0,
2128         vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
2129         *computeModule,                  // shader
2130         "main",
2131         nullptr, // pSpecializationInfo
2132     };
2133     const vk::VkComputePipelineCreateInfo createInfo = {
2134         vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2135         nullptr,
2136         0u,             // flags
2137         cs,             // cs
2138         layout,         // layout
2139         VK_NULL_HANDLE, // basePipelineHandle
2140         0u,             // basePipelineIndex
2141     };
2142     return createComputePipeline(vki, device, VK_NULL_HANDLE, &createInfo);
2143 }
2144 
2145 class ComputeCommand
2146 {
2147 public:
2148     ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2149                    vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2150                    ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2151                    const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets, const uint32_t *dynamicOffsets,
2152                    int numPreBarriers, const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2153                    const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2);
2154 
2155     void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2156 #ifndef CTS_USES_VULKANSC
2157                        ,
2158                        std::vector<UpdateTemplateHandleSp> *updateTemplates = nullptr,
2159                        std::vector<RawUpdateRegistry> *updateRegistry       = nullptr
2160 #endif
2161     ) const;
2162 #ifndef CTS_USES_VULKANSC
2163     void submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue, vk::DescriptorSetUpdateBuilder &updateBuilder,
2164                        std::vector<uint32_t> &descriptorsPerSet) const;
2165 #endif
2166 
2167 private:
2168     const bool m_bind2;
2169     const vk::DeviceInterface &m_vki;
2170     const vk::VkDevice m_device;
2171     const vk::VkPipeline m_pipeline;
2172     const vk::VkPipelineLayout m_pipelineLayout;
2173     const tcu::UVec3 m_numWorkGroups;
2174     const ShaderInputInterface m_shaderInterface;
2175     const DescriptorSetCount m_descriptorSetCount;
2176     const vk::VkDescriptorSet *const m_descriptorSets;
2177     const int m_numDynamicOffsets;
2178     const uint32_t *const m_dynamicOffsets;
2179     const int m_numPreBarriers;
2180     const vk::VkBufferMemoryBarrier *const m_preBarriers;
2181     const int m_numPostBarriers;
2182     const vk::VkBufferMemoryBarrier *const m_postBarriers;
2183 };
2184 
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)2185 ComputeCommand::ComputeCommand(const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkPipeline pipeline,
2186                                vk::VkPipelineLayout pipelineLayout, const tcu::UVec3 &numWorkGroups,
2187                                ShaderInputInterface shaderInterface, DescriptorSetCount descriptorSetCount,
2188                                const vk::VkDescriptorSet *descriptorSets, int numDynamicOffsets,
2189                                const uint32_t *dynamicOffsets, int numPreBarriers,
2190                                const vk::VkBufferMemoryBarrier *preBarriers, int numPostBarriers,
2191                                const vk::VkBufferMemoryBarrier *postBarriers, const bool bind2)
2192     : m_bind2(bind2)
2193     , m_vki(vki)
2194     , m_device(device)
2195     , m_pipeline(pipeline)
2196     , m_pipelineLayout(pipelineLayout)
2197     , m_numWorkGroups(numWorkGroups)
2198     , m_shaderInterface(shaderInterface)
2199     , m_descriptorSetCount(descriptorSetCount)
2200     , m_descriptorSets(descriptorSets)
2201     , m_numDynamicOffsets(numDynamicOffsets)
2202     , m_dynamicOffsets(dynamicOffsets)
2203     , m_numPreBarriers(numPreBarriers)
2204     , m_preBarriers(preBarriers)
2205     , m_numPostBarriers(numPostBarriers)
2206     , m_postBarriers(postBarriers)
2207 {
2208 }
2209 
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,std::vector<UpdateTemplateHandleSp> * updateTemplates,std::vector<RawUpdateRegistry> * updateRegistry) const2210 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue
2211 #ifndef CTS_USES_VULKANSC
2212                                    ,
2213                                    std::vector<UpdateTemplateHandleSp> *updateTemplates,
2214                                    std::vector<RawUpdateRegistry> *updateRegistry
2215 #endif
2216 ) const
2217 {
2218     const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2219         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr,
2220         vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2221         queueFamilyIndex,                         // queueFamilyIndex
2222     };
2223     const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2224 
2225     const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = {
2226         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
2227         nullptr,
2228         *cmdPool,                            // cmdPool
2229         vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
2230         1u,                                  // count
2231     };
2232 
2233     const vk::Unique<vk::VkCommandBuffer> cmd(vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
2234 
2235     beginCommandBuffer(m_vki, *cmd);
2236 
2237     m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2238 
2239     // normal update
2240 #ifndef CTS_USES_VULKANSC
2241     if (updateTemplates == nullptr)
2242 #endif
2243     {
2244         switch (m_descriptorSetCount)
2245         {
2246         case DESCRIPTOR_SET_COUNT_SINGLE:
2247         case DESCRIPTOR_SET_COUNT_MULTIPLE:
2248         {
2249             bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2250                                vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0,
2251                                getDescriptorSetCount(m_descriptorSetCount), m_descriptorSets, m_numDynamicOffsets,
2252                                m_dynamicOffsets, m_bind2);
2253             break;
2254         }
2255         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
2256         {
2257             uint32_t dynamicOffsetNdx = 0u;
2258 
2259             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2260             {
2261                 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
2262                 const uint32_t numOffsets =
2263                     (!m_numDynamicOffsets) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
2264                 const uint32_t *const dynamicOffsetPtr =
2265                     (!m_numDynamicOffsets) ? (nullptr) : (&m_dynamicOffsets[dynamicOffsetNdx]);
2266                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
2267 
2268                 bindDescriptorSets(m_vki, *cmd, vk::VK_SHADER_STAGE_COMPUTE_BIT, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2269                                    vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, descriptorSetNdx, 1u,
2270                                    &m_descriptorSets[setNdx], numOffsets, dynamicOffsetPtr, m_bind2);
2271 
2272                 dynamicOffsetNdx += getInterfaceNumResources(m_shaderInterface);
2273             }
2274             break;
2275         }
2276         default:
2277             DE_FATAL("Impossible");
2278         }
2279     }
2280 #ifndef CTS_USES_VULKANSC
2281     // update with push template
2282     else
2283     {
2284         for (uint32_t setNdx = 0; setNdx < (uint32_t)(*updateTemplates).size(); setNdx++)
2285             m_vki.cmdPushDescriptorSetWithTemplate(*cmd, **(*updateTemplates)[setNdx], m_pipelineLayout,
2286                                                    getDescriptorSetNdx(m_descriptorSetCount, setNdx),
2287                                                    (const void *)(*updateRegistry)[setNdx].getRawPointer());
2288     }
2289 #endif
2290 
2291     if (m_numPreBarriers)
2292         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2293                                  (vk::VkDependencyFlags)0, 0, nullptr, m_numPreBarriers, m_preBarriers, 0, nullptr);
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, nullptr, m_numPostBarriers, m_postBarriers, 0, nullptr);
2298     endCommandBuffer(m_vki, *cmd);
2299 
2300     submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2301 }
2302 
2303 #ifndef CTS_USES_VULKANSC
2304 //cmdPushDescriptorSet variant
submitAndWait(uint32_t queueFamilyIndex,vk::VkQueue queue,vk::DescriptorSetUpdateBuilder & updateBuilder,std::vector<uint32_t> & descriptorsPerSet) const2305 void ComputeCommand::submitAndWait(uint32_t queueFamilyIndex, vk::VkQueue queue,
2306                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
2307                                    std::vector<uint32_t> &descriptorsPerSet) const
2308 {
2309     const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = {
2310         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr,
2311         vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
2312         queueFamilyIndex,                         // queueFamilyIndex
2313     };
2314     const vk::Unique<vk::VkCommandPool> cmdPool(vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
2315 
2316     const vk::Unique<vk::VkCommandBuffer> cmd(
2317         vk::allocateCommandBuffer(m_vki, m_device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2318 
2319     beginCommandBuffer(m_vki, *cmd);
2320 
2321     m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
2322 
2323     {
2324         uint32_t descriptorNdx = 0u;
2325         for (uint32_t setNdx = 0; setNdx < (uint32_t)descriptorsPerSet.size(); setNdx++)
2326         {
2327             const uint32_t numDescriptors = descriptorsPerSet[setNdx];
2328             updateBuilder.updateWithPush(m_vki, *cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout,
2329                                          getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
2330                                          numDescriptors);
2331             descriptorNdx += numDescriptors;
2332         }
2333     }
2334 
2335     if (m_numPreBarriers)
2336         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2337                                  (vk::VkDependencyFlags)0, 0, nullptr, m_numPreBarriers, m_preBarriers, 0, nullptr);
2338 
2339     m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
2340     m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT,
2341                              (vk::VkDependencyFlags)0, 0, nullptr, m_numPostBarriers, m_postBarriers, 0, nullptr);
2342     endCommandBuffer(m_vki, *cmd);
2343 
2344     submitCommandsAndWait(m_vki, m_device, queue, cmd.get());
2345 }
2346 #endif
2347 
2348 class BufferComputeInstance : public vkt::TestInstance
2349 {
2350 public:
2351     BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
2352                           DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, bool viewOffset,
2353                           bool dynamicOffset, bool dynamicOffsetNonZero, bool bind2);
2354 
2355 private:
2356     vk::Move<vk::VkBuffer> createColorDataBuffer(uint32_t offset, uint32_t bufferSize, const tcu::Vec4 &value1,
2357                                                  const tcu::Vec4 &value2, de::MovePtr<vk::Allocation> *outAllocation);
2358     vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
2359     vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
2360     vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
2361                                                       uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2362                                                       vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2363     void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA,
2364                             vk::VkBuffer viewB, uint32_t offsetB, vk::VkBuffer resBuf);
2365 #ifndef CTS_USES_VULKANSC
2366     void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
2367                                         uint32_t setNdx, vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2368                                         uint32_t offsetB, vk::VkBuffer resBuf, bool withPush = false,
2369                                         vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
2370 #endif
2371 
2372     tcu::TestStatus iterate(void);
2373     void logTestPlan(void) const;
2374     tcu::TestStatus testResourceAccess(void);
2375 
2376     enum
2377     {
2378         STATIC_OFFSET_VALUE_A  = 256,
2379         DYNAMIC_OFFSET_VALUE_A = 512,
2380         STATIC_OFFSET_VALUE_B  = 1024,
2381         DYNAMIC_OFFSET_VALUE_B = 768,
2382     };
2383 
2384     const DescriptorUpdateMethod m_updateMethod;
2385     const vk::VkDescriptorType m_descriptorType;
2386     const DescriptorSetCount m_descriptorSetCount;
2387     const ShaderInputInterface m_shaderInterface;
2388     const bool m_setViewOffset;
2389     const bool m_setDynamicOffset;
2390     const bool m_dynamicOffsetNonZero;
2391     const bool m_bind2;
2392 
2393 #ifndef CTS_USES_VULKANSC
2394     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
2395 #endif
2396     const vk::DeviceInterface &m_vki;
2397     const vk::VkDevice m_device;
2398     const vk::VkQueue m_queue;
2399     const uint32_t m_queueFamilyIndex;
2400     vk::Allocator &m_allocator;
2401 
2402     const ComputeInstanceResultBuffer m_result;
2403 
2404 #ifndef CTS_USES_VULKANSC
2405     std::vector<RawUpdateRegistry> m_updateRegistry;
2406 #endif
2407     vk::DescriptorSetUpdateBuilder m_updateBuilder;
2408     std::vector<uint32_t> m_descriptorsPerSet;
2409 };
2410 
BufferComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,bool viewOffset,bool dynamicOffset,bool dynamicOffsetNonZero,bool bind2)2411 BufferComputeInstance::BufferComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
2412                                              vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
2413                                              ShaderInputInterface shaderInterface, bool viewOffset, bool dynamicOffset,
2414                                              bool dynamicOffsetNonZero, bool bind2)
2415     : vkt::TestInstance(context)
2416     , m_updateMethod(updateMethod)
2417     , m_descriptorType(descriptorType)
2418     , m_descriptorSetCount(descriptorSetCount)
2419     , m_shaderInterface(shaderInterface)
2420     , m_setViewOffset(viewOffset)
2421     , m_setDynamicOffset(dynamicOffset)
2422     , m_dynamicOffsetNonZero(dynamicOffsetNonZero)
2423     , m_bind2(bind2)
2424 #ifndef CTS_USES_VULKANSC
2425     , m_updateTemplates()
2426 #endif
2427     , m_vki(context.getDeviceInterface())
2428     , m_device(context.getDevice())
2429     , m_queue(context.getUniversalQueue())
2430     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
2431     , m_allocator(context.getDefaultAllocator())
2432     , m_result(m_vki, m_device, m_allocator)
2433 #ifndef CTS_USES_VULKANSC
2434     , m_updateRegistry()
2435 #endif
2436     , m_updateBuilder()
2437     , m_descriptorsPerSet()
2438 {
2439     if (m_dynamicOffsetNonZero)
2440         DE_ASSERT(m_setDynamicOffset);
2441 }
2442 
createColorDataBuffer(uint32_t offset,uint32_t bufferSize,const tcu::Vec4 & value1,const tcu::Vec4 & value2,de::MovePtr<vk::Allocation> * outAllocation)2443 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer(uint32_t offset, uint32_t bufferSize,
2444                                                                     const tcu::Vec4 &value1, const tcu::Vec4 &value2,
2445                                                                     de::MovePtr<vk::Allocation> *outAllocation)
2446 {
2447     DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
2448 
2449     const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2450     const vk::VkBufferUsageFlags usageFlags =
2451         (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2452     const vk::VkBufferCreateInfo createInfo = {
2453         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
2454         nullptr,
2455         0u,                            // flags
2456         (vk::VkDeviceSize)bufferSize,  // size
2457         usageFlags,                    // usage
2458         vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2459         0u,                            // queueFamilyCount
2460         nullptr,                       // pQueueFamilyIndices
2461     };
2462     vk::Move<vk::VkBuffer> buffer(vk::createBuffer(m_vki, m_device, &createInfo));
2463     de::MovePtr<vk::Allocation> allocation(
2464         allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
2465     void *mapPtr = allocation->getHostPtr();
2466 
2467     if (offset)
2468         deMemset(mapPtr, 0x5A, (size_t)offset);
2469     deMemcpy((uint8_t *)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
2470     deMemcpy((uint8_t *)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
2471     deMemset((uint8_t *)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A,
2472              (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
2473 
2474     flushAlloc(m_vki, m_device, *allocation);
2475 
2476     *outAllocation = allocation;
2477     return buffer;
2478 }
2479 
createDescriptorSetLayout(uint32_t setNdx) const2480 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
2481 {
2482     vk::DescriptorSetLayoutBuilder builder;
2483     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
2484     uint32_t binding                                = 0;
2485 
2486 #ifndef CTS_USES_VULKANSC
2487     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
2488         m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2489     {
2490         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
2491     }
2492 #endif
2493 
2494     if (setNdx == 0)
2495         builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
2496                                         binding++);
2497 
2498     switch (m_shaderInterface)
2499     {
2500     case SHADER_INPUT_SINGLE_DESCRIPTOR:
2501         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2502         break;
2503 
2504     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2505         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2506         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2507         break;
2508 
2509     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2510         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 0u);
2511         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2u);
2512         break;
2513 
2514     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2515         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
2516         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
2517         break;
2518 
2519     case SHADER_INPUT_DESCRIPTOR_ARRAY:
2520         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2521         break;
2522 
2523     default:
2524         DE_FATAL("Impossible");
2525     }
2526 
2527     return builder.build(m_vki, m_device, extraFlags);
2528 }
2529 
createDescriptorPool(void) const2530 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool(void) const
2531 {
2532     return vk::DescriptorPoolBuilder()
2533         .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2534         .addType(m_descriptorType,
2535                  getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
2536         .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
2537                getDescriptorSetCount(m_descriptorSetCount));
2538 }
2539 
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)2540 vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
2541                                                                          vk::VkDescriptorSetLayout layout,
2542                                                                          uint32_t setNdx, vk::VkBuffer viewA,
2543                                                                          uint32_t offsetA, vk::VkBuffer viewB,
2544                                                                          uint32_t offsetB, vk::VkBuffer resBuf)
2545 {
2546     const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
2547                                                        pool, 1u, &layout};
2548 
2549     vk::Move<vk::VkDescriptorSet> descriptorSet;
2550     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
2551         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2552     {
2553         descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
2554     }
2555     else
2556     {
2557         descriptorSet = vk::Move<vk::VkDescriptorSet>();
2558     }
2559 
2560 #ifndef CTS_USES_VULKANSC
2561     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
2562     {
2563         writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2564     }
2565     else
2566 #endif
2567         if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2568     {
2569         writeDescriptorSet(*descriptorSet, setNdx, viewA, offsetA, viewB, offsetB, resBuf);
2570     }
2571 
2572     return descriptorSet;
2573 }
2574 
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx,vk::VkBuffer viewA,uint32_t offsetA,vk::VkBuffer viewB,uint32_t offsetB,vk::VkBuffer resBuf)2575 void BufferComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkBuffer viewA,
2576                                                uint32_t offsetA, vk::VkBuffer viewB, uint32_t offsetB,
2577                                                vk::VkBuffer resBuf)
2578 {
2579     const vk::VkDescriptorBufferInfo resultInfo =
2580         vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2581     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2582         vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2583         vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2584     };
2585 
2586     uint32_t numDescriptors = 0u;
2587     uint32_t binding        = 0u;
2588 
2589     // result
2590     if (setNdx == 0)
2591     {
2592         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2593                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
2594         numDescriptors++;
2595     }
2596 
2597     // buffers
2598     switch (m_shaderInterface)
2599     {
2600     case SHADER_INPUT_SINGLE_DESCRIPTOR:
2601         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2602                                     m_descriptorType, &bufferInfos[0]);
2603         numDescriptors++;
2604         break;
2605 
2606     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2607         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2608                                     m_descriptorType, &bufferInfos[0]);
2609         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2610                                     m_descriptorType, &bufferInfos[1]);
2611         numDescriptors += 2;
2612         break;
2613 
2614     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2615         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
2616                                     m_descriptorType, &bufferInfos[0]);
2617         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
2618                                     m_descriptorType, &bufferInfos[1]);
2619         numDescriptors += 2;
2620         break;
2621 
2622     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2623         m_updateBuilder.writeSingle(descriptorSet,
2624                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
2625                                     m_descriptorType, &bufferInfos[0]);
2626         m_updateBuilder.writeSingle(descriptorSet,
2627                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
2628                                     m_descriptorType, &bufferInfos[1]);
2629         numDescriptors += 2;
2630         break;
2631 
2632     case SHADER_INPUT_DESCRIPTOR_ARRAY:
2633         m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
2634                                    m_descriptorType, 2u, bufferInfos);
2635         numDescriptors++;
2636         break;
2637 
2638     default:
2639         DE_FATAL("Impossible");
2640     }
2641 
2642     m_descriptorsPerSet.push_back(numDescriptors);
2643 
2644     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
2645     {
2646         m_updateBuilder.update(m_vki, m_device);
2647         m_updateBuilder.clear();
2648     }
2649 }
2650 
2651 #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)2652 void BufferComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
2653                                                            vk::VkDescriptorSetLayout layout, uint32_t setNdx,
2654                                                            vk::VkBuffer viewA, uint32_t offsetA, vk::VkBuffer viewB,
2655                                                            uint32_t offsetB, vk::VkBuffer resBuf, bool withPush,
2656                                                            vk::VkPipelineLayout pipelineLayout)
2657 {
2658     const vk::VkDescriptorBufferInfo resultInfo =
2659         vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2660     const vk::VkDescriptorBufferInfo bufferInfos[2] = {
2661         vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2662         vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2663     };
2664     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
2665     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
2666         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
2667         nullptr,
2668         0,
2669         0,       // descriptorUpdateEntryCount
2670         nullptr, // pDescriptorUpdateEntries
2671         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
2672                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
2673         layout,
2674         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
2675         pipelineLayout,
2676         setNdx};
2677     uint32_t binding = 0u;
2678     uint32_t offset  = 0u;
2679     RawUpdateRegistry updateRegistry;
2680 
2681     if (setNdx == 0)
2682         updateRegistry.addWriteObject(resultInfo);
2683 
2684     updateRegistry.addWriteObject(bufferInfos[0]);
2685     updateRegistry.addWriteObject(bufferInfos[1]);
2686 
2687     // result
2688     if (setNdx == 0)
2689         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
2690                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2691 
2692     // buffers
2693     switch (m_shaderInterface)
2694     {
2695     case SHADER_INPUT_SINGLE_DESCRIPTOR:
2696         updateEntries.push_back(
2697             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2698         break;
2699 
2700     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
2701         updateEntries.push_back(
2702             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2703         updateEntries.push_back(
2704             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2705         break;
2706 
2707     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
2708         updateEntries.push_back(
2709             createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
2710         updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
2711                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2712         break;
2713 
2714     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
2715         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
2716                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2717         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
2718                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
2719         break;
2720 
2721     case SHADER_INPUT_DESCRIPTOR_ARRAY:
2722         updateEntries.push_back(createTemplateBinding(
2723             binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(bufferInfos[0])));
2724         break;
2725 
2726     default:
2727         DE_FATAL("Impossible");
2728     }
2729 
2730     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
2731     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
2732 
2733     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
2734         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
2735     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
2736     m_updateRegistry.push_back(updateRegistry);
2737 
2738     if (!withPush)
2739     {
2740         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
2741                                               m_updateRegistry.back().getRawPointer());
2742     }
2743 }
2744 #endif
2745 
iterate(void)2746 tcu::TestStatus BufferComputeInstance::iterate(void)
2747 {
2748     logTestPlan();
2749     return testResourceAccess();
2750 }
2751 
logTestPlan(void) const2752 void BufferComputeInstance::logTestPlan(void) const
2753 {
2754     std::ostringstream msg;
2755 
2756     msg << "Accessing resource in a compute program.\n"
2757         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
2758                                                                     "Multiple descriptor sets. ")
2759         << "Each descriptor set contains "
2760         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
2761             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
2762             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
2763             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
2764             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
2765                                                                                      nullptr)
2766         << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2767         << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2768         << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2769 
2770     if (isDynamicDescriptorType(m_descriptorType))
2771     {
2772         if (m_setDynamicOffset)
2773         {
2774             msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2775                 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2776         }
2777         else
2778         {
2779             msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2780         }
2781     }
2782 
2783     msg << "Destination buffer is pre-initialized to -1.\n";
2784 
2785     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
2786 }
2787 
testResourceAccess(void)2788 tcu::TestStatus BufferComputeInstance::testResourceAccess(void)
2789 {
2790     enum
2791     {
2792         ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2793     };
2794 
2795     const bool isDynamicCase   = isDynamicDescriptorType(m_descriptorType);
2796     const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType);
2797 
2798     const tcu::Vec4 color[] = {
2799         tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), // green
2800         tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), // yellow
2801         tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), // blue
2802         tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), // red
2803     };
2804 
2805     std::vector<uint32_t> bindTimeOffsets;
2806     std::vector<tcu::Vec4> colors;
2807     std::vector<uint32_t> dataOffsets;
2808     std::vector<uint32_t> viewOffsets;
2809     std::vector<uint32_t> bufferSizes;
2810     std::vector<AllocationSp> bufferMems;
2811     std::vector<BufferHandleSp> buffers;
2812 
2813     for (uint32_t bufferNdx = 0;
2814          bufferNdx < getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2815          bufferNdx++)
2816     {
2817         const uint32_t staticOffsets[] = {STATIC_OFFSET_VALUE_A, STATIC_OFFSET_VALUE_B};
2818 
2819         const uint32_t dynamicOffset[] = {DYNAMIC_OFFSET_VALUE_A, DYNAMIC_OFFSET_VALUE_B};
2820 
2821         const uint32_t parity = bufferNdx % 2;
2822         bindTimeOffsets.push_back((m_dynamicOffsetNonZero) ? (dynamicOffset[parity]) : (0u));
2823 
2824         const uint32_t dataOffset =
2825             ((isDynamicCase) ? (bindTimeOffsets.back()) : 0) + ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2826         const uint32_t viewOffset = ((m_setViewOffset) ? (staticOffsets[parity]) : (0u));
2827 
2828         colors.push_back(color[bufferNdx % DE_LENGTH_OF_ARRAY(color)]);
2829         dataOffsets.push_back(dataOffset);
2830         viewOffsets.push_back(viewOffset);
2831         bufferSizes.push_back(dataOffsets.back() + ADDRESSABLE_SIZE);
2832 
2833         de::MovePtr<vk::Allocation> bufferMem;
2834         vk::Move<vk::VkBuffer> buffer(createColorDataBuffer(
2835             dataOffsets.back(), bufferSizes.back(), color[(bufferNdx * 2) % DE_LENGTH_OF_ARRAY(color)],
2836             color[(bufferNdx * 2 + 1) % DE_LENGTH_OF_ARRAY(color)], &bufferMem));
2837 
2838         bufferMems.push_back(AllocationSp(bufferMem.release()));
2839         buffers.push_back(BufferHandleSp(new BufferHandleUp(buffer)));
2840     }
2841 
2842     const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
2843     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
2844     std::vector<DescriptorSetHandleSp> descriptorSets;
2845     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
2846     std::vector<vk::VkDescriptorSet> setHandles;
2847 
2848     const uint32_t numSrcBuffers =
2849         getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface);
2850 
2851     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2852     {
2853         const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2854         const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2855 
2856         vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
2857         vk::Move<vk::VkDescriptorSet> set =
2858             createDescriptorSet(*descriptorPool, *layout, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1],
2859                                 viewOffsets[ndx1], m_result.getBuffer());
2860 
2861         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
2862         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
2863 
2864         layoutHandles.push_back(**descriptorSetLayouts.back());
2865         setHandles.push_back(**descriptorSets.back());
2866 
2867         // Add an empty descriptor set layout between sets 0 and 2
2868         if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
2869         {
2870             vk::DescriptorSetLayoutBuilder emptyBuilder;
2871             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
2872                 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
2873 
2874             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
2875             layoutHandles.push_back(**descriptorSetLayouts.back());
2876         }
2877     }
2878 
2879     const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
2880                                    &layoutHandles.front());
2881     const vk::VkAccessFlags inputBit =
2882         (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT);
2883 
2884     std::vector<vk::VkBufferMemoryBarrier> bufferBarriers;
2885 
2886     for (uint32_t bufferNdx = 0; bufferNdx < numSrcBuffers; bufferNdx++)
2887     {
2888         const vk::VkBufferMemoryBarrier barrier = {
2889             vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2890             nullptr,
2891             vk::VK_ACCESS_HOST_WRITE_BIT,             // srcAccessMask
2892             inputBit,                                 // dstAccessMask
2893             VK_QUEUE_FAMILY_IGNORED,                  // srcQueueFamilyIndex
2894             VK_QUEUE_FAMILY_IGNORED,                  // destQueueFamilyIndex
2895             **buffers[bufferNdx],                     // buffer
2896             (vk::VkDeviceSize)0u,                     // offset
2897             (vk::VkDeviceSize)bufferSizes[bufferNdx], // size
2898         };
2899 
2900         bufferBarriers.push_back(barrier);
2901     }
2902 
2903     const uint32_t *const dynamicOffsets                = (m_setDynamicOffset) ? (&bindTimeOffsets.front()) : (nullptr);
2904     const uint32_t numDynamicOffsets                    = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2905     const vk::VkBufferMemoryBarrier *const preBarriers  = &bufferBarriers.front();
2906     const int numPreBarriers                            = numSrcBuffers;
2907     const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
2908     const int numPostBarriers                           = 1;
2909 
2910     const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
2911                                  tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
2912                                  numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
2913                                  postBarriers, m_bind2);
2914 
2915     tcu::Vec4 refQuadrantValue14 = tcu::Vec4(0.0f);
2916     tcu::Vec4 refQuadrantValue23 = tcu::Vec4(0.0f);
2917 
2918     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2919     {
2920         uint32_t offset = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? 1 : 3;
2921         refQuadrantValue14 +=
2922             color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface) + offset) % DE_LENGTH_OF_ARRAY(color)];
2923         refQuadrantValue23 +=
2924             color[(2 * setNdx * getInterfaceNumResources(m_shaderInterface)) % DE_LENGTH_OF_ARRAY(color)];
2925     }
2926 
2927     refQuadrantValue14 = refQuadrantValue14 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2928     refQuadrantValue23 = refQuadrantValue23 / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
2929 
2930     const tcu::Vec4 references[4] = {
2931         refQuadrantValue14,
2932         refQuadrantValue23,
2933         refQuadrantValue23,
2934         refQuadrantValue14,
2935     };
2936     tcu::Vec4 results[4];
2937 
2938 #ifndef CTS_USES_VULKANSC
2939     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
2940     {
2941         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2942         {
2943             const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2944             const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2945 
2946             writeDescriptorSetWithTemplate(VK_NULL_HANDLE, layoutHandles[setNdx], setNdx, **buffers[ndx0],
2947                                            viewOffsets[ndx0], **buffers[ndx1], viewOffsets[ndx1], m_result.getBuffer(),
2948                                            true, pipeline.getPipelineLayout());
2949         }
2950         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
2951     }
2952     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
2953     {
2954         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
2955         {
2956             const uint32_t ndx0 = (setNdx * getInterfaceNumResources(m_shaderInterface)) % numSrcBuffers;
2957             const uint32_t ndx1 = (setNdx * getInterfaceNumResources(m_shaderInterface) + 1) % numSrcBuffers;
2958 
2959             writeDescriptorSet(VK_NULL_HANDLE, setNdx, **buffers[ndx0], viewOffsets[ndx0], **buffers[ndx1],
2960                                viewOffsets[ndx1], m_result.getBuffer());
2961         }
2962 
2963         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
2964     }
2965     else
2966 #endif
2967     {
2968         compute.submitAndWait(m_queueFamilyIndex, m_queue);
2969     }
2970     m_result.readResultContentsTo(&results);
2971 
2972     // verify
2973     if (results[0] == references[0] && results[1] == references[1] && results[2] == references[2] &&
2974         results[3] == references[3])
2975     {
2976         return tcu::TestStatus::pass("Pass");
2977     }
2978     else if (results[0] == tcu::Vec4(-1.0f) && results[1] == tcu::Vec4(-1.0f) && results[2] == tcu::Vec4(-1.0f) &&
2979              results[3] == tcu::Vec4(-1.0f))
2980     {
2981         m_context.getTestContext().getLog()
2982             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
2983         return tcu::TestStatus::fail("Result buffer was not written to");
2984     }
2985     else
2986     {
2987         m_context.getTestContext().getLog()
2988             << tcu::TestLog::Message << "Error expected [" << references[0] << ", " << references[1] << ", "
2989             << references[2] << ", " << references[3] << "], got [" << results[0] << ", " << results[1] << ", "
2990             << results[2] << ", " << results[3] << "]" << tcu::TestLog::EndMessage;
2991         return tcu::TestStatus::fail("Invalid result values");
2992     }
2993 }
2994 
2995 class QuadrantRendederCase : public vkt::TestCase
2996 {
2997 public:
2998     QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
2999                          vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3000                          DescriptorSetCount descriptorSetCount);
3001 
3002 private:
3003     virtual std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const                     = 0;
3004     virtual std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0;
3005     virtual std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const                      = 0;
3006     virtual std::string genNoAccessSource(void) const                                                       = 0;
3007 
3008     std::string genVertexSource(void) const;
3009     std::string genTessCtrlSource(void) const;
3010     std::string genTessEvalSource(void) const;
3011     std::string genGeometrySource(void) const;
3012     std::string genFragmentSource(void) const;
3013     std::string genComputeSource(void) const;
3014 
3015     void initPrograms(vk::SourceCollections &programCollection) const;
3016 
3017 protected:
3018     const glu::GLSLVersion m_glslVersion;
3019     const vk::VkShaderStageFlags m_exitingStages;
3020     const vk::VkShaderStageFlags m_activeStages;
3021     const DescriptorSetCount m_descriptorSetCount;
3022 };
3023 
QuadrantRendederCase(tcu::TestContext & testCtx,const char * name,glu::GLSLVersion glslVersion,vk::VkShaderStageFlags exitingStages,vk::VkShaderStageFlags activeStages,DescriptorSetCount descriptorSetCount)3024 QuadrantRendederCase::QuadrantRendederCase(tcu::TestContext &testCtx, const char *name, glu::GLSLVersion glslVersion,
3025                                            vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3026                                            DescriptorSetCount descriptorSetCount)
3027     : vkt::TestCase(testCtx, name)
3028     , m_glslVersion(glslVersion)
3029     , m_exitingStages(exitingStages)
3030     , m_activeStages(activeStages)
3031     , m_descriptorSetCount(descriptorSetCount)
3032 {
3033     DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
3034 }
3035 
genVertexSource(void) const3036 std::string QuadrantRendederCase::genVertexSource(void) const
3037 {
3038     const char *const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ?
3039                                           ("tsc") :
3040                                       ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo") :
3041                                       ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag") :
3042                                                                                                      (nullptr);
3043     const char *const fragColorPrec =
3044         ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? "highp" : "mediump";
3045     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3046     std::ostringstream buf;
3047 
3048     if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3049     {
3050         const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT);
3051 
3052         // active vertex shader
3053         buf << versionDecl << "\n" << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT);
3054         buf << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0);
3055         buf << "layout(location = 0) out " << fragColorPrec << " vec4 " << nextStageName << "_color;\n"
3056             << (onlyVS ? "" :
3057                          "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n")
3058             << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3059             << "{\n"
3060             << "    highp vec4 result_position;\n"
3061             << "    highp int quadrant_id;\n"
3062             << s_quadrantGenVertexPosSource << "    gl_Position = result_position;\n"
3063             << (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n") << "\n"
3064             << "    highp vec4 result_color;\n"
3065             << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT) << "    " << nextStageName
3066             << "_color = result_color;\n"
3067             << "}\n";
3068     }
3069     else
3070     {
3071         // do nothing
3072         buf << versionDecl << "\n"
3073             << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT) << "layout(location = 1) flat out highp int "
3074             << nextStageName << "_quadrant_id;\n"
3075             << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) << "void main (void)\n"
3076             << "{\n"
3077             << "    highp vec4 result_position;\n"
3078             << "    highp int quadrant_id;\n"
3079             << s_quadrantGenVertexPosSource << "    gl_Position = result_position;\n"
3080             << "    " << nextStageName << "_quadrant_id = quadrant_id;\n"
3081             << "}\n";
3082     }
3083 
3084     return buf.str();
3085 }
3086 
genTessCtrlSource(void) const3087 std::string QuadrantRendederCase::genTessCtrlSource(void) const
3088 {
3089     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3090     const bool extRequired        = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3091     const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3092     std::ostringstream buf;
3093 
3094     if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3095     {
3096         // contributing not implemented
3097         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3098 
3099         // active tc shader
3100         buf << versionDecl << "\n"
3101             << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
3102             << "layout(vertices=3) out;\n"
3103             << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0)
3104             << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3105             << "layout(location = 0) out highp vec4 tes_color[];\n"
3106             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3107             << "{\n"
3108             << "    highp vec4 result_color;\n"
3109             << "    highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
3110             << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) << "\n"
3111             << "    tes_color[gl_InvocationID] = result_color;\n"
3112             << "\n"
3113             << "    // no dynamic input block indexing\n"
3114             << "    highp vec4 position;\n"
3115             << "    if (gl_InvocationID == 0)\n"
3116             << "        position = gl_in[0].gl_Position;\n"
3117             << "    else if (gl_InvocationID == 1)\n"
3118             << "        position = gl_in[1].gl_Position;\n"
3119             << "    else\n"
3120             << "        position = gl_in[2].gl_Position;\n"
3121             << "    gl_out[gl_InvocationID].gl_Position = position;\n"
3122             << "    gl_TessLevelInner[0] = 2.8;\n"
3123             << "    gl_TessLevelInner[1] = 2.8;\n"
3124             << "    gl_TessLevelOuter[0] = 2.8;\n"
3125             << "    gl_TessLevelOuter[1] = 2.8;\n"
3126             << "    gl_TessLevelOuter[2] = 2.8;\n"
3127             << "    gl_TessLevelOuter[3] = 2.8;\n"
3128             << "}\n";
3129     }
3130     else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3131     {
3132         // active te shader, tc passthru
3133         buf << versionDecl << "\n"
3134             << tessExtDecl << "layout(vertices=3) out;\n"
3135             << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
3136             << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
3137             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) << "void main (void)\n"
3138             << "{\n"
3139             << "    tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
3140             << "\n"
3141             << "    // no dynamic input block indexing\n"
3142             << "    highp vec4 position;\n"
3143             << "    if (gl_InvocationID == 0)\n"
3144             << "        position = gl_in[0].gl_Position;\n"
3145             << "    else if (gl_InvocationID == 1)\n"
3146             << "        position = gl_in[1].gl_Position;\n"
3147             << "    else\n"
3148             << "        position = gl_in[2].gl_Position;\n"
3149             << "    gl_out[gl_InvocationID].gl_Position = position;\n"
3150             << "    gl_TessLevelInner[0] = 2.8;\n"
3151             << "    gl_TessLevelInner[1] = 2.8;\n"
3152             << "    gl_TessLevelOuter[0] = 2.8;\n"
3153             << "    gl_TessLevelOuter[1] = 2.8;\n"
3154             << "    gl_TessLevelOuter[2] = 2.8;\n"
3155             << "    gl_TessLevelOuter[3] = 2.8;\n"
3156             << "}\n";
3157     }
3158     else
3159     {
3160         // passthrough not implemented
3161         DE_FATAL("not implemented");
3162     }
3163 
3164     return buf.str();
3165 }
3166 
genTessEvalSource(void) const3167 std::string QuadrantRendederCase::genTessEvalSource(void) const
3168 {
3169     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3170     const bool extRequired        = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3171     const char *const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
3172     std::ostringstream buf;
3173 
3174     if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3175     {
3176         // contributing not implemented
3177         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
3178 
3179         // active te shader
3180         buf << versionDecl << "\n"
3181             << tessExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3182             << "layout(triangles) in;\n"
3183             << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0)
3184             << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
3185             << "layout(location = 0) out mediump vec4 frag_color;\n"
3186             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3187             << "{\n"
3188             << "    highp vec4 result_color;\n"
3189             << "    highp int quadrant_id = tes_quadrant_id[0];\n"
3190             << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) << "\n"
3191             << "    frag_color = result_color;\n"
3192             << "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3193                "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3194             << "}\n";
3195     }
3196     else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3197     {
3198         // contributing not implemented
3199         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3200 
3201         // active tc shader, te is passthru
3202         buf << versionDecl << "\n"
3203             << tessExtDecl << "layout(triangles) in;\n"
3204             << "layout(location = 0) in highp vec4 tes_color[];\n"
3205             << "layout(location = 0) out mediump vec4 frag_color;\n"
3206             << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) << "void main (void)\n"
3207             << "{\n"
3208             << "    frag_color = tes_color[0];\n"
3209             << "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
3210                "gl_TessCoord.z * gl_in[2].gl_Position;\n"
3211             << "}\n";
3212     }
3213     else
3214     {
3215         // passthrough not implemented
3216         DE_FATAL("not implemented");
3217     }
3218 
3219     return buf.str();
3220 }
3221 
genGeometrySource(void) const3222 std::string QuadrantRendederCase::genGeometrySource(void) const
3223 {
3224     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3225     const bool extRequired        = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
3226     const char *const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
3227     std::ostringstream buf;
3228 
3229     if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3230     {
3231         // contributing not implemented
3232         DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
3233 
3234         // active geometry shader
3235         buf << versionDecl << "\n"
3236             << geomExtDecl << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "layout(triangles) in;\n"
3237             << "layout(triangle_strip, max_vertices=4) out;\n"
3238             << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0)
3239             << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
3240             << "layout(location = 0) out mediump vec4 frag_color;\n"
3241             << genPerVertexBlock(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_glslVersion) << "void main (void)\n"
3242             << "{\n"
3243             << "    highp int quadrant_id;\n"
3244             << "    highp vec4 result_color;\n"
3245             << "\n"
3246             << "    quadrant_id = geo_quadrant_id[0];\n"
3247             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3248             << "    gl_Position = gl_in[0].gl_Position;\n"
3249             << "    EmitVertex();\n"
3250             << "\n"
3251             << "    quadrant_id = geo_quadrant_id[1];\n"
3252             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3253             << "    gl_Position = gl_in[1].gl_Position;\n"
3254             << "    EmitVertex();\n"
3255             << "\n"
3256             << "    quadrant_id = geo_quadrant_id[2];\n"
3257             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3258             << "    gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
3259             << "    EmitVertex();\n"
3260             << "\n"
3261             << "    quadrant_id = geo_quadrant_id[0];\n"
3262             << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) << "    frag_color = result_color;\n"
3263             << "    gl_Position = gl_in[2].gl_Position;\n"
3264             << "    EmitVertex();\n"
3265             << "}\n";
3266     }
3267     else
3268     {
3269         // passthrough not implemented
3270         DE_FATAL("not implemented");
3271     }
3272 
3273     return buf.str();
3274 }
3275 
genFragmentSource(void) const3276 std::string QuadrantRendederCase::genFragmentSource(void) const
3277 {
3278     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3279     std::ostringstream buf;
3280 
3281     if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3282     {
3283         buf << versionDecl << "\n"
3284             << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT)
3285             << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0);
3286 
3287         if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3288         {
3289             // there are other stages, this is just a contributor
3290             buf << "layout(location = 0) in mediump vec4 frag_color;\n";
3291         }
3292 
3293         buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3294             << "layout(location = 0) out mediump vec4 o_color;\n"
3295             << "void main (void)\n"
3296             << "{\n"
3297             << "    highp int quadrant_id = frag_quadrant_id;\n"
3298             << "    highp vec4 result_color;\n"
3299             << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT);
3300 
3301         if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
3302         {
3303             // just contributor
3304             buf << "    if (frag_quadrant_id < 2)\n"
3305                 << "        o_color = result_color;\n"
3306                 << "    else\n"
3307                 << "        o_color = frag_color;\n";
3308         }
3309         else
3310             buf << "    o_color = result_color;\n";
3311 
3312         buf << "}\n";
3313     }
3314     else if (m_activeStages == 0u)
3315     {
3316         // special case, no active stages
3317         buf << versionDecl << "\n"
3318             << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
3319             << "layout(location = 0) out mediump vec4 o_color;\n"
3320             << "void main (void)\n"
3321             << "{\n"
3322             << "    highp int quadrant_id = frag_quadrant_id;\n"
3323             << "    highp vec4 result_color;\n"
3324             << genNoAccessSource() << "    o_color = result_color;\n"
3325             << "}\n";
3326     }
3327     else
3328     {
3329         // passthrough
3330         buf << versionDecl << "\n"
3331             << "layout(location = 0) in mediump vec4 frag_color;\n"
3332                "layout(location = 0) out mediump vec4 o_color;\n"
3333                "void main (void)\n"
3334                "{\n"
3335                "    o_color = frag_color;\n"
3336                "}\n";
3337     }
3338 
3339     return buf.str();
3340 }
3341 
genComputeSource(void) const3342 std::string QuadrantRendederCase::genComputeSource(void) const
3343 {
3344     const char *const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion);
3345     std::ostringstream buf;
3346 
3347     buf << versionDecl << "\n"
3348         << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3349         << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3350         << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1)
3351         << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
3352         << "{\n"
3353         << "    highp vec4 read_colors[4];\n"
3354         << "} b_out;\n"
3355         << "void main (void)\n"
3356         << "{\n"
3357         << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
3358         << "    highp vec4 result_color;\n"
3359         << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT)
3360         << "    b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
3361         << "}\n";
3362 
3363     return buf.str();
3364 }
3365 
initPrograms(vk::SourceCollections & programCollection) const3366 void QuadrantRendederCase::initPrograms(vk::SourceCollections &programCollection) const
3367 {
3368     if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
3369         programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
3370 
3371     if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u)
3372         programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
3373 
3374     if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u)
3375         programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
3376 
3377     if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
3378         programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
3379 
3380     if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
3381         programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
3382 
3383     if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
3384         programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
3385 }
3386 
3387 class BufferDescriptorCase : public QuadrantRendederCase
3388 {
3389 public:
3390     enum
3391     {
3392         FLAG_VIEW_OFFSET            = (1u << 1u),
3393         FLAG_DYNAMIC_OFFSET_ZERO    = (1u << 2u),
3394         FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u),
3395     };
3396     // enum continues where resource flags ends
3397     DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
3398 
3399     BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
3400                          bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3401                          vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3402                          DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags,
3403                          const bool bind2);
3404 
3405 private:
3406     std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
3407     std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
3408     std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
3409     std::string genNoAccessSource(void) const;
3410 
3411     vkt::TestInstance *createInstance(vkt::Context &context) const;
3412 
3413     void checkSupport(Context &context) const;
3414 
3415     const DescriptorUpdateMethod m_updateMethod;
3416     const bool m_viewOffset;
3417     const bool m_dynamicOffsetSet;
3418     const bool m_dynamicOffsetNonZero;
3419     const bool m_isPrimaryCmdBuf;
3420     const vk::VkDescriptorType m_descriptorType;
3421     const DescriptorSetCount m_descriptorSetCount;
3422     const ShaderInputInterface m_shaderInterface;
3423     const bool m_bind2;
3424 };
3425 
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)3426 BufferDescriptorCase::BufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod,
3427                                            const char *name, bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
3428                                            vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
3429                                            DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3430                                            uint32_t flags, const bool bind2)
3431     : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
3432     , m_updateMethod(updateMethod)
3433     , m_viewOffset((flags & FLAG_VIEW_OFFSET) != 0u)
3434     , m_dynamicOffsetSet((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
3435     , m_dynamicOffsetNonZero((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
3436     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
3437     , m_descriptorType(descriptorType)
3438     , m_descriptorSetCount(descriptorSetCount)
3439     , m_shaderInterface(shaderInterface)
3440     , m_bind2(bind2)
3441 {
3442 }
3443 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const3444 std::string BufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
3445 {
3446     DE_UNREF(stage);
3447     return "";
3448 }
3449 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const3450 std::string BufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const
3451 {
3452     DE_UNREF(stage);
3453 
3454     const bool isUniform          = isUniformDescriptorType(m_descriptorType);
3455     const char *const storageType = (isUniform) ? ("uniform") : ("buffer");
3456     const uint32_t numSets        = getDescriptorSetCount(m_descriptorSetCount);
3457 
3458     std::ostringstream buf;
3459 
3460     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3461     {
3462         // Result buffer is bound only to the first descriptor set in compute shader cases
3463         const int descBinding =
3464             numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
3465         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3466         const uint32_t descriptorSet    = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
3467 
3468         switch (m_shaderInterface)
3469         {
3470         case SHADER_INPUT_SINGLE_DESCRIPTOR:
3471             buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3472                 << " BufferName" << setNdxPostfix << "\n"
3473                 << "{\n"
3474                 << "    highp vec4 colorA;\n"
3475                 << "    highp vec4 colorB;\n"
3476                 << "} b_instance" << setNdxPostfix << ";\n";
3477             break;
3478 
3479         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3480             buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3481                 << " BufferName" << setNdxPostfix << "A\n"
3482                 << "{\n"
3483                 << "    highp vec4 colorA;\n"
3484                 << "    highp vec4 colorB;\n"
3485                 << "} b_instance" << setNdxPostfix << "A;\n"
3486                 << "layout(set = " << descriptorSet << ", binding = " << (descBinding + 1) << ", std140) "
3487                 << storageType << " BufferName" << setNdxPostfix << "B\n"
3488                 << "{\n"
3489                 << "    highp vec4 colorA;\n"
3490                 << "    highp vec4 colorB;\n"
3491                 << "} b_instance" << setNdxPostfix << "B;\n";
3492             break;
3493 
3494         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3495             buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding) << ", std140) "
3496                 << storageType << " BufferName" << setNdxPostfix << "A\n"
3497                 << "{\n"
3498                 << "    highp vec4 colorA;\n"
3499                 << "    highp vec4 colorB;\n"
3500                 << "} b_instance" << setNdxPostfix << "A;\n"
3501                 << "layout(set = " << descriptorSet << ", binding = " << de::toString(descBinding + 2) << ", std140) "
3502                 << storageType << " BufferName" << setNdxPostfix << "B\n"
3503                 << "{\n"
3504                 << "    highp vec4 colorA;\n"
3505                 << "    highp vec4 colorB;\n"
3506                 << "} b_instance" << setNdxPostfix << "B;\n";
3507             break;
3508 
3509         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3510             buf << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(0))
3511                 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "A\n"
3512                 << "{\n"
3513                 << "    highp vec4 colorA;\n"
3514                 << "    highp vec4 colorB;\n"
3515                 << "} b_instance" << setNdxPostfix << "A;\n"
3516                 << "layout(set = " << descriptorSet << ", binding = " << de::toString(getArbitraryBindingIndex(1))
3517                 << ", std140) " << storageType << " BufferName" << setNdxPostfix << "B\n"
3518                 << "{\n"
3519                 << "    highp vec4 colorA;\n"
3520                 << "    highp vec4 colorB;\n"
3521                 << "} b_instance" << setNdxPostfix << "B;\n";
3522             break;
3523 
3524         case SHADER_INPUT_DESCRIPTOR_ARRAY:
3525             buf << "layout(set = " << descriptorSet << ", binding = " << (descBinding) << ", std140) " << storageType
3526                 << " BufferName" << setNdxPostfix << "\n"
3527                 << "{\n"
3528                 << "    highp vec4 colorA;\n"
3529                 << "    highp vec4 colorB;\n"
3530                 << "} b_instances" << setNdxPostfix << "[2];\n";
3531             break;
3532 
3533         default:
3534             DE_FATAL("Impossible");
3535         }
3536     }
3537     return buf.str();
3538 }
3539 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const3540 std::string BufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
3541 {
3542     DE_UNREF(stage);
3543 
3544     const uint32_t numSets = getDescriptorSetCount(m_descriptorSetCount);
3545     std::ostringstream buf;
3546 
3547     buf << "    result_color = vec4(0.0);\n";
3548 
3549     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
3550     {
3551         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
3552 
3553         switch (m_shaderInterface)
3554         {
3555         case SHADER_INPUT_SINGLE_DESCRIPTOR:
3556             buf << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3557                 << "        result_color += b_instance" << setNdxPostfix << ".colorA;\n"
3558                 << "    else\n"
3559                 << "        result_color += b_instance" << setNdxPostfix << ".colorB;\n";
3560             break;
3561 
3562         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
3563         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
3564         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
3565             buf << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3566                 << "        result_color += b_instance" << setNdxPostfix << "A.colorA;\n"
3567                 << "    else\n"
3568                 << "        result_color += b_instance" << setNdxPostfix << "B.colorB;\n";
3569             break;
3570 
3571         case SHADER_INPUT_DESCRIPTOR_ARRAY:
3572             buf << "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3573                 << "        result_color += b_instances" << setNdxPostfix << "[0].colorA;\n"
3574                 << "    else\n"
3575                 << "        result_color += b_instances" << setNdxPostfix << "[1].colorB;\n";
3576             break;
3577 
3578         default:
3579             DE_FATAL("Impossible");
3580         }
3581     }
3582 
3583     if (getDescriptorSetCount(m_descriptorSetCount) > 1)
3584         buf << "    result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
3585 
3586     return buf.str();
3587 }
3588 
genNoAccessSource(void) const3589 std::string BufferDescriptorCase::genNoAccessSource(void) const
3590 {
3591     return "    if (quadrant_id == 1 || quadrant_id == 2)\n"
3592            "        result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
3593            "    else\n"
3594            "        result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
3595 }
3596 
createInstance(vkt::Context & context) const3597 vkt::TestInstance *BufferDescriptorCase::createInstance(vkt::Context &context) const
3598 {
3599     verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
3600                         m_updateMethod, m_descriptorType, m_activeStages);
3601 
3602     if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
3603     {
3604         DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
3605         return new BufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
3606                                          m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero,
3607                                          m_bind2);
3608     }
3609     else
3610         return new BufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
3611                                         m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
3612                                         m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero, m_bind2);
3613 }
3614 
checkSupport(Context & context) const3615 void BufferDescriptorCase::checkSupport(Context &context) const
3616 {
3617     if (m_bind2)
3618         context.requireDeviceFunctionality("VK_KHR_maintenance6");
3619 }
3620 
3621 class ImageInstanceImages
3622 {
3623 public:
3624     ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3625                         vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3626                         vk::VkImageViewType viewType, int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3627                         uint32_t baseArraySlice);
3628 
3629 private:
3630     static std::vector<tcu::TextureLevelPyramid> createSourceImages(int numImages, int numLevels,
3631                                                                     vk::VkImageViewType viewType,
3632                                                                     tcu::TextureFormat imageFormat);
3633 
3634     static std::vector<ImageHandleSp> createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3635                                                    vk::Allocator &allocator, uint32_t queueFamilyIndex,
3636                                                    vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3637                                                    vk::VkImageViewType viewType, std::vector<AllocationSp> &imageMemory,
3638                                                    const std::vector<tcu::TextureLevelPyramid> &sourceImages);
3639 
3640     static std::vector<ImageViewHandleSp> createImageViews(const vk::DeviceInterface &vki, vk::VkDevice device,
3641                                                            vk::VkImageViewType viewType,
3642                                                            const std::vector<tcu::TextureLevelPyramid> &sourceImages,
3643                                                            const std::vector<ImageHandleSp> &images,
3644                                                            uint32_t baseMipLevel, uint32_t baseArraySlice);
3645 
3646     static vk::Move<vk::VkImage> createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3647                                              vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3648                                              vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &sourceImage,
3649                                              de::MovePtr<vk::Allocation> *outAllocation);
3650 
3651     static vk::Move<vk::VkImageView> createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3652                                                      vk::VkImageViewType viewType,
3653                                                      const tcu::TextureLevelPyramid &sourceImage, vk::VkImage image,
3654                                                      uint32_t baseMipLevel, uint32_t baseArraySlice);
3655 
3656     static void populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx);
3657 
3658     static void uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3659                             vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image, vk::VkImageLayout layout,
3660                             vk::VkImageViewType viewType, const tcu::TextureLevelPyramid &data);
3661 
3662 protected:
3663     enum
3664     {
3665         IMAGE_SIZE = 64,
3666         ARRAY_SIZE = 2,
3667     };
3668 
3669     const vk::VkImageViewType m_viewType;
3670     const uint32_t m_baseMipLevel;
3671     const uint32_t m_baseArraySlice;
3672     const tcu::TextureFormat m_imageFormat;
3673     const std::vector<tcu::TextureLevelPyramid> m_sourceImage;
3674     std::vector<AllocationSp> m_imageMemory;
3675     const std::vector<ImageHandleSp> m_image;
3676     const std::vector<ImageViewHandleSp> m_imageView;
3677 };
3678 
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)3679 ImageInstanceImages::ImageInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3680                                          vk::VkQueue queue, vk::Allocator &allocator,
3681                                          vk::VkDescriptorType descriptorType, vk::VkImageViewType viewType,
3682                                          int numImages, uint32_t numLevels, uint32_t baseMipLevel,
3683                                          uint32_t baseArraySlice)
3684     : m_viewType(viewType)
3685     , m_baseMipLevel(baseMipLevel)
3686     , m_baseArraySlice(baseArraySlice)
3687     , m_imageFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
3688     , m_sourceImage(createSourceImages(numImages, numLevels, viewType, m_imageFormat))
3689     , m_imageMemory()
3690     , m_image(createImages(vki, device, allocator, queueFamilyIndex, queue, descriptorType, viewType, m_imageMemory,
3691                            m_sourceImage))
3692     , m_imageView(createImageViews(vki, device, viewType, m_sourceImage, m_image, m_baseMipLevel, m_baseArraySlice))
3693 {
3694 }
3695 
createSourceImages(int numImages,int numLevels,vk::VkImageViewType viewType,tcu::TextureFormat imageFormat)3696 std::vector<tcu::TextureLevelPyramid> ImageInstanceImages::createSourceImages(int numImages, int numLevels,
3697                                                                               vk::VkImageViewType viewType,
3698                                                                               tcu::TextureFormat imageFormat)
3699 {
3700     std::vector<tcu::TextureLevelPyramid> sourceImages(numImages, tcu::TextureLevelPyramid(imageFormat, numLevels));
3701 
3702     for (int imageNdx = 0; imageNdx < numImages; imageNdx++)
3703         populateSourceImage(&sourceImages.at(imageNdx), viewType, imageNdx);
3704 
3705     return sourceImages;
3706 }
3707 
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)3708 std::vector<ImageHandleSp> ImageInstanceImages::createImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3709                                                              vk::Allocator &allocator, uint32_t queueFamilyIndex,
3710                                                              vk::VkQueue queue, vk::VkDescriptorType descriptorType,
3711                                                              vk::VkImageViewType viewType,
3712                                                              std::vector<AllocationSp> &imageMemory,
3713                                                              const std::vector<tcu::TextureLevelPyramid> &sourceImages)
3714 {
3715     std::vector<ImageHandleSp> images;
3716     const vk::VkImageLayout layout = getImageLayoutForDescriptorType(descriptorType);
3717 
3718     for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3719     {
3720         de::MovePtr<vk::Allocation> memory;
3721         vk::Move<vk::VkImage> image =
3722             createImage(vki, device, allocator, descriptorType, viewType, sourceImages[imageNdx], &memory);
3723 
3724         uploadImage(vki, device, queueFamilyIndex, queue, allocator, *image, layout, viewType, sourceImages[imageNdx]);
3725 
3726         imageMemory.push_back(AllocationSp(memory.release()));
3727         images.push_back(ImageHandleSp(new ImageHandleUp(image)));
3728     }
3729     return images;
3730 }
3731 
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)3732 std::vector<ImageViewHandleSp> ImageInstanceImages::createImageViews(
3733     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkImageViewType viewType,
3734     const std::vector<tcu::TextureLevelPyramid> &sourceImages, const std::vector<ImageHandleSp> &images,
3735     uint32_t baseMipLevel, uint32_t baseArraySlice)
3736 {
3737     std::vector<ImageViewHandleSp> imageViews;
3738     for (int imageNdx = 0; imageNdx < (int)sourceImages.size(); imageNdx++)
3739     {
3740         vk::Move<vk::VkImageView> imageView = createImageView(vki, device, viewType, sourceImages[imageNdx],
3741                                                               **images[imageNdx], baseMipLevel, baseArraySlice);
3742         imageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imageView)));
3743     }
3744     return imageViews;
3745 }
3746 
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)3747 vk::Move<vk::VkImage> ImageInstanceImages::createImage(const vk::DeviceInterface &vki, vk::VkDevice device,
3748                                                        vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3749                                                        vk::VkImageViewType viewType,
3750                                                        const tcu::TextureLevelPyramid &sourceImage,
3751                                                        de::MovePtr<vk::Allocation> *outAllocation)
3752 {
3753     const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3754     const bool isCube    = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
3755     const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
3756     const uint32_t readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
3757     const uint32_t arraySize =
3758         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3759             (baseLevel.getHeight()) :
3760         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ?
3761             (baseLevel.getDepth()) :
3762         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3763         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3764                                                   (baseLevel.getDepth()) // cube: numFaces * numLayers
3765                                                   :
3766                                                   (0);
3767     const vk::VkExtent3D extent = {
3768         // x
3769         (uint32_t)baseLevel.getWidth(),
3770 
3771         // y
3772         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3773             (1u) :
3774             (uint32_t)baseLevel.getHeight(),
3775 
3776         // z
3777         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((uint32_t)baseLevel.getDepth()) : (1u),
3778     };
3779     const vk::VkImageCreateInfo createInfo = {
3780         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3781         nullptr,
3782         isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0,
3783         viewTypeToImageType(viewType),                   // imageType
3784         vk::mapTextureFormat(baseLevel.getFormat()),     // format
3785         extent,                                          // extent
3786         (uint32_t)sourceImage.getNumLevels(),            // mipLevels
3787         arraySize,                                       // arraySize
3788         vk::VK_SAMPLE_COUNT_1_BIT,                       // samples
3789         vk::VK_IMAGE_TILING_OPTIMAL,                     // tiling
3790         readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage
3791         vk::VK_SHARING_MODE_EXCLUSIVE,                   // sharingMode
3792         0u,                                              // queueFamilyCount
3793         nullptr,                                         // pQueueFamilyIndices
3794         vk::VK_IMAGE_LAYOUT_UNDEFINED,                   // initialLayout
3795     };
3796     vk::Move<vk::VkImage> image(vk::createImage(vki, device, &createInfo));
3797 
3798     *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
3799     return image;
3800 }
3801 
createImageView(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkImageViewType viewType,const tcu::TextureLevelPyramid & sourceImage,vk::VkImage image,uint32_t baseMipLevel,uint32_t baseArraySlice)3802 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView(const vk::DeviceInterface &vki, vk::VkDevice device,
3803                                                                vk::VkImageViewType viewType,
3804                                                                const tcu::TextureLevelPyramid &sourceImage,
3805                                                                vk::VkImage image, uint32_t baseMipLevel,
3806                                                                uint32_t baseArraySlice)
3807 {
3808     const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0);
3809     const uint32_t viewTypeBaseSlice =
3810         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3811             (6 * baseArraySlice) :
3812             (baseArraySlice);
3813     const uint32_t viewArraySize =
3814         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D)         ? (1) :
3815         (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)   ? (baseLevel.getHeight() - viewTypeBaseSlice) :
3816         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D)         ? (1) :
3817         (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)   ? (baseLevel.getDepth() - viewTypeBaseSlice) :
3818         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)         ? (1) :
3819         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)       ? (6) :
3820         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() -
3821                                                            viewTypeBaseSlice) // cube: numFaces * numLayers
3822                                                           :
3823                                                           (0);
3824 
3825     DE_ASSERT(viewArraySize > 0);
3826 
3827     const vk::VkImageSubresourceRange resourceRange = {
3828         vk::VK_IMAGE_ASPECT_COLOR_BIT,             // aspectMask
3829         baseMipLevel,                              // baseMipLevel
3830         sourceImage.getNumLevels() - baseMipLevel, // mipLevels
3831         viewTypeBaseSlice,                         // baseArraySlice
3832         viewArraySize,                             // arraySize
3833     };
3834     const vk::VkImageViewCreateInfo createInfo = {
3835         vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
3836         nullptr,
3837         (vk::VkImageViewCreateFlags)0,
3838         image,                                       // image
3839         viewType,                                    // viewType
3840         vk::mapTextureFormat(baseLevel.getFormat()), // format
3841         {vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B,
3842          vk::VK_COMPONENT_SWIZZLE_A}, // channels
3843         resourceRange,                // subresourceRange
3844     };
3845     return vk::createImageView(vki, device, &createInfo);
3846 }
3847 
populateSourceImage(tcu::TextureLevelPyramid * dst,vk::VkImageViewType viewType,int imageNdx)3848 void ImageInstanceImages::populateSourceImage(tcu::TextureLevelPyramid *dst, vk::VkImageViewType viewType, int imageNdx)
3849 {
3850     const int numLevels = dst->getNumLevels();
3851 
3852     for (int level = 0; level < numLevels; ++level)
3853     {
3854         const int width  = IMAGE_SIZE >> level;
3855         const int height = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ?
3856                                (ARRAY_SIZE) :
3857                                (IMAGE_SIZE >> level);
3858         const int depth =
3859             (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) :
3860             (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE) :
3861             (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3862                                                                                                      (6 * ARRAY_SIZE) :
3863             (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level) :
3864                                                       (1);
3865 
3866         dst->allocLevel(level, width, height, depth);
3867 
3868         {
3869             const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
3870 
3871             for (int z = 0; z < depth; ++z)
3872                 for (int y = 0; y < height; ++y)
3873                     for (int x = 0; x < width; ++x)
3874                     {
3875                         const int gradPos = x + y + z;
3876                         const int gradMax = width + height + depth - 3;
3877 
3878                         int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors)
3879                         int green =
3880                             ((gradPos % 2 == 0) ? (127) : (0)) +
3881                             ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors)
3882                         int blue =
3883                             (128 * level / numLevels) +
3884                             ((imageNdx % 2 == 0) ? 127 : 0); //!< level and image index (detects incorrect lod / image)
3885 
3886                         DE_ASSERT(de::inRange(red, 0, 255));
3887                         DE_ASSERT(de::inRange(green, 0, 255));
3888                         DE_ASSERT(de::inRange(blue, 0, 255));
3889 
3890                         if (imageNdx % 3 == 0)
3891                             red = 255 - red;
3892                         if (imageNdx % 4 == 0)
3893                             green = 255 - green;
3894                         if (imageNdx % 5 == 0)
3895                             blue = 255 - blue;
3896 
3897                         levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3898                     }
3899         }
3900     }
3901 }
3902 
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)3903 void ImageInstanceImages::uploadImage(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3904                                       vk::VkQueue queue, vk::Allocator &allocator, vk::VkImage image,
3905                                       vk::VkImageLayout layout, vk::VkImageViewType viewType,
3906                                       const tcu::TextureLevelPyramid &data)
3907 {
3908     const uint32_t arraySize =
3909         (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3910         (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ?
3911                                                   (6 * (uint32_t)ARRAY_SIZE) :
3912                                                   ((uint32_t)ARRAY_SIZE);
3913     const uint32_t dataBufferSize                 = getTextureLevelPyramidDataSize(data);
3914     const vk::VkBufferCreateInfo bufferCreateInfo = {
3915         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3916         nullptr,
3917         0u,                                   // flags
3918         dataBufferSize,                       // size
3919         vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
3920         vk::VK_SHARING_MODE_EXCLUSIVE,        // sharingMode
3921         0u,                                   // queueFamilyCount
3922         nullptr,                              // pQueueFamilyIndices
3923     };
3924 
3925     const vk::Unique<vk::VkBuffer> dataBuffer(vk::createBuffer(vki, device, &bufferCreateInfo));
3926     const de::MovePtr<vk::Allocation> dataBufferMemory =
3927         allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3928     std::vector<vk::VkBufferImageCopy> copySlices;
3929     // copy data to buffer
3930     writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, viewType, &copySlices);
3931     flushAlloc(vki, device, *dataBufferMemory);
3932 
3933     // copy buffer to image
3934     copyBufferToImage(vki, device, queue, queueFamilyIndex, *dataBuffer, dataBufferSize, copySlices, nullptr,
3935                       vk::VK_IMAGE_ASPECT_COLOR_BIT, data.getNumLevels(), arraySize, image, layout);
3936 }
3937 
3938 class ImageFetchInstanceImages : private ImageInstanceImages
3939 {
3940 public:
3941     ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
3942                              vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3943                              DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
3944                              vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
3945                              uint32_t baseArraySlice);
3946 
3947     static tcu::IVec3 getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
3948                                   int fetchPosNdx);
3949 
3950     tcu::Vec4 fetchImageValue(int fetchPosNdx, int setNdx) const;
3951 
getSourceImage(int ndx) const3952     inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
3953     {
3954         return m_sourceImage[ndx];
3955     }
getImageView(int ndx) const3956     inline vk::VkImageView getImageView(int ndx) const
3957     {
3958         return **m_imageView[ndx % m_imageView.size()];
3959     }
3960 
3961 private:
3962     enum
3963     {
3964         // some arbitrary sample points for all four quadrants
3965         SAMPLE_POINT_0_X = 6,
3966         SAMPLE_POINT_0_Y = 13,
3967         SAMPLE_POINT_0_Z = 49,
3968 
3969         SAMPLE_POINT_1_X = 51,
3970         SAMPLE_POINT_1_Y = 40,
3971         SAMPLE_POINT_1_Z = 44,
3972 
3973         SAMPLE_POINT_2_X = 42,
3974         SAMPLE_POINT_2_Y = 26,
3975         SAMPLE_POINT_2_Z = 19,
3976 
3977         SAMPLE_POINT_3_X = 25,
3978         SAMPLE_POINT_3_Y = 25,
3979         SAMPLE_POINT_3_Z = 18,
3980     };
3981 
3982     const ShaderInputInterface m_shaderInterface;
3983 };
3984 
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)3985 ImageFetchInstanceImages::ImageFetchInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
3986                                                    uint32_t queueFamilyIndex, vk::VkQueue queue,
3987                                                    vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
3988                                                    DescriptorSetCount descriptorSetCount,
3989                                                    ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
3990                                                    uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice)
3991     : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
3992                           getDescriptorSetCount(descriptorSetCount) *
3993                               getInterfaceNumResources(shaderInterface), // numImages
3994                           numLevels, baseMipLevel, baseArraySlice)
3995     , m_shaderInterface(shaderInterface)
3996 {
3997 }
3998 
isImageViewTypeArray(vk::VkImageViewType type)3999 bool isImageViewTypeArray(vk::VkImageViewType type)
4000 {
4001     return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY ||
4002            type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
4003 }
4004 
getFetchPos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int fetchPosNdx)4005 tcu::IVec3 ImageFetchInstanceImages::getFetchPos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
4006                                                  uint32_t baseArraySlice, int fetchPosNdx)
4007 {
4008     const tcu::IVec3 fetchPositions[4] = {
4009         tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
4010         tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
4011         tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
4012         tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
4013     };
4014     const tcu::IVec3 coord   = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
4015     const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
4016     const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
4017 
4018     switch (viewType)
4019     {
4020     case vk::VK_IMAGE_VIEW_TYPE_1D:
4021     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
4022         return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
4023     case vk::VK_IMAGE_VIEW_TYPE_2D:
4024     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
4025         return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
4026     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4027     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
4028         return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
4029     case vk::VK_IMAGE_VIEW_TYPE_3D:
4030         return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
4031     default:
4032         DE_FATAL("Impossible");
4033         return tcu::IVec3();
4034     }
4035 }
4036 
fetchImageValue(int fetchPosNdx,int setNdx) const4037 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue(int fetchPosNdx, int setNdx) const
4038 {
4039     DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
4040 
4041     const tcu::TextureLevelPyramid &fetchSrcA = getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface));
4042     const tcu::TextureLevelPyramid &fetchSrcB =
4043         (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
4044             fetchSrcA :
4045             getSourceImage(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
4046     const tcu::TextureLevelPyramid &fetchSrc =
4047         ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
4048     tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
4049 
4050     // add base array layer into the appropriate coordinate, based on the view type
4051     if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
4052         fetchPos.z() += 6 * m_baseArraySlice;
4053     else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
4054         fetchPos.y() += m_baseArraySlice;
4055     else
4056         fetchPos.z() += m_baseArraySlice;
4057 
4058     return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
4059 }
4060 
4061 class ImageFetchRenderInstance : public SingleCmdRenderInstance
4062 {
4063 public:
4064     ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
4065                              vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4066                              vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
4067                              ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4068                              uint32_t baseArraySlice, const bool bind2);
4069 
4070 private:
4071     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
4072         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4073         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4074         DescriptorUpdateMethod updateMethod);
4075 
4076     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
4077         const vk::DeviceInterface &vki, vk::VkDevice device,
4078         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
4079 
4080     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
4081                                                                vk::VkDescriptorType descriptorType,
4082                                                                DescriptorSetCount descriptorSetCount,
4083                                                                ShaderInputInterface shaderInterface);
4084 
4085     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
4086         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4087         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4088         ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
4089         vk::VkDescriptorPool pool, const ImageFetchInstanceImages &images,
4090         vk::DescriptorSetUpdateBuilder &updateBuilder,
4091 #ifndef CTS_USES_VULKANSC
4092         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4093 #endif
4094         std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
4095 
4096     static void writeDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
4097                                    vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface,
4098                                    vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool, vk::VkImageView viewA,
4099                                    vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4100                                    vk::DescriptorSetUpdateBuilder &updateBuilder,
4101                                    std::vector<uint32_t> &descriptorsPerSet,
4102                                    DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
4103 
4104 #ifndef CTS_USES_VULKANSC
4105     static void writeDescriptorSetWithTemplate(const vk::DeviceInterface &vki, vk::VkDevice device,
4106                                                vk::VkDescriptorType descriptorType,
4107                                                ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout,
4108                                                vk::VkDescriptorPool pool, vk::VkImageView viewA, vk::VkImageView viewB,
4109                                                vk::VkDescriptorSet descriptorSet,
4110                                                std::vector<UpdateTemplateHandleSp> &updateTemplates,
4111                                                std::vector<RawUpdateRegistry> &registry, bool withPush = false,
4112                                                vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
4113 #endif
4114 
4115     void logTestPlan(void) const;
4116     vk::VkPipelineLayout getPipelineLayout(void) const;
4117     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
4118     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
4119 
4120     enum
4121     {
4122         RENDER_SIZE = 128,
4123     };
4124 
4125     const DescriptorUpdateMethod m_updateMethod;
4126     const vk::VkDescriptorType m_descriptorType;
4127     const DescriptorSetCount m_descriptorSetCount;
4128     const vk::VkShaderStageFlags m_stageFlags;
4129     const vk::VkShaderStageFlags m_existingStages;
4130     const ShaderInputInterface m_shaderInterface;
4131     const vk::VkImageViewType m_viewType;
4132     const uint32_t m_numLevels;
4133     const uint32_t m_baseMipLevel;
4134     const uint32_t m_baseArraySlice;
4135 
4136 #ifndef CTS_USES_VULKANSC
4137     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4138     std::vector<RawUpdateRegistry> m_updateRegistry;
4139 #endif
4140     vk::DescriptorSetUpdateBuilder m_updateBuilder;
4141     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
4142     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
4143     const ImageFetchInstanceImages m_images;
4144     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
4145     std::vector<uint32_t> m_descriptorsPerSet;
4146     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
4147 };
4148 
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)4149 ImageFetchRenderInstance::ImageFetchRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4150                                                    bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
4151                                                    DescriptorSetCount descriptorSetCount,
4152                                                    vk::VkShaderStageFlags stageFlags,
4153                                                    vk::VkShaderStageFlags existingStages,
4154                                                    ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4155                                                    uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4156     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
4157     , m_updateMethod(updateMethod)
4158     , m_descriptorType(descriptorType)
4159     , m_descriptorSetCount(descriptorSetCount)
4160     , m_stageFlags(stageFlags)
4161     , m_existingStages(existingStages)
4162     , m_shaderInterface(shaderInterface)
4163     , m_viewType(viewType)
4164     , m_numLevels(baseMipLevel + 1u)
4165     , m_baseMipLevel(baseMipLevel)
4166     , m_baseArraySlice(baseArraySlice)
4167 #ifndef CTS_USES_VULKANSC
4168     , m_updateTemplates()
4169     , m_updateRegistry()
4170 #endif
4171     , m_updateBuilder()
4172     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
4173                                                         m_shaderInterface, m_stageFlags, m_updateMethod))
4174     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
4175     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4176                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4177     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
4178     , m_descriptorsPerSet()
4179     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
4180                                             m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, m_images,
4181                                             m_updateBuilder,
4182 #ifndef CTS_USES_VULKANSC
4183                                             m_updateTemplates, m_updateRegistry,
4184 #endif
4185                                             m_descriptorsPerSet, *m_pipelineLayout))
4186 {
4187 }
4188 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,DescriptorUpdateMethod updateMethod)4189 std::vector<DescriptorSetLayoutHandleSp> ImageFetchRenderInstance::createDescriptorSetLayouts(
4190     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4191     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
4192     DescriptorUpdateMethod updateMethod)
4193 {
4194 #ifdef CTS_USES_VULKANSC
4195     DE_UNREF(updateMethod);
4196 #endif
4197     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
4198     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4199 
4200 #ifndef CTS_USES_VULKANSC
4201     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4202         updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4203     {
4204         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4205     }
4206 #endif
4207 
4208     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4209     {
4210         vk::DescriptorSetLayoutBuilder builder;
4211 
4212         switch (shaderInterface)
4213         {
4214         case SHADER_INPUT_SINGLE_DESCRIPTOR:
4215             builder.addSingleBinding(descriptorType, stageFlags);
4216             break;
4217 
4218         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4219             builder.addSingleBinding(descriptorType, stageFlags);
4220             builder.addSingleBinding(descriptorType, stageFlags);
4221             break;
4222 
4223         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4224             builder.addSingleIndexedBinding(descriptorType, stageFlags, 0u);
4225             builder.addSingleIndexedBinding(descriptorType, stageFlags, 2u);
4226             break;
4227 
4228         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4229             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0));
4230             builder.addSingleIndexedBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1));
4231             break;
4232 
4233         case SHADER_INPUT_DESCRIPTOR_ARRAY:
4234             builder.addArrayBinding(descriptorType, 2u, stageFlags);
4235             break;
4236 
4237         default:
4238             DE_FATAL("Impossible");
4239         }
4240 
4241         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
4242         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
4243 
4244         // Add an empty descriptor set layout between sets 0 and 2
4245         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
4246         {
4247             vk::DescriptorSetLayoutBuilder emptyBuilder;
4248             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
4249                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
4250             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
4251         }
4252     }
4253     return descriptorSetLayouts;
4254 }
4255 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)4256 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout(
4257     const vk::DeviceInterface &vki, vk::VkDevice device,
4258     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
4259 {
4260     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
4261     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
4262         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
4263 
4264     const vk::VkPipelineLayoutCreateInfo createInfo = {
4265         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4266         nullptr,
4267         (vk::VkPipelineLayoutCreateFlags)0,
4268         (uint32_t)layoutHandles.size(), // descriptorSetCount
4269         &layoutHandles.front(),         // pSetLayouts
4270         0u,                             // pushConstantRangeCount
4271         nullptr,                        // pPushConstantRanges
4272     };
4273     return vk::createPipelineLayout(vki, device, &createInfo);
4274 }
4275 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)4276 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
4277                                                                               vk::VkDevice device,
4278                                                                               vk::VkDescriptorType descriptorType,
4279                                                                               DescriptorSetCount descriptorSetCount,
4280                                                                               ShaderInputInterface shaderInterface)
4281 {
4282     return vk::DescriptorPoolBuilder()
4283         .addType(descriptorType, getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface))
4284         .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4285                getDescriptorSetCount(descriptorSetCount));
4286 }
4287 
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)4288 std::vector<DescriptorSetHandleSp> ImageFetchRenderInstance::createDescriptorSets(
4289     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
4290     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
4291     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool,
4292     const ImageFetchInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
4293 #ifndef CTS_USES_VULKANSC
4294     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
4295 #endif
4296     std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
4297 {
4298 #ifdef CTS_USES_VULKANSC
4299     DE_UNREF(pipelineLayout);
4300 #endif
4301     std::vector<DescriptorSetHandleSp> descriptorSets;
4302 
4303     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
4304     {
4305         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
4306 
4307         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
4308                                                            pool, 1u, &layout};
4309 
4310         vk::VkImageView viewA = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface));
4311         vk::VkImageView viewB = images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1);
4312 
4313         vk::Move<vk::VkDescriptorSet> descriptorSet;
4314         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4315             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4316         {
4317             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
4318         }
4319         else
4320         {
4321             descriptorSet = vk::Move<vk::VkDescriptorSet>();
4322         }
4323 
4324 #ifndef CTS_USES_VULKANSC
4325         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4326         {
4327             writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4328                                            *descriptorSet, updateTemplates, updateRegistry);
4329         }
4330         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4331         {
4332             writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB,
4333                                            *descriptorSet, updateTemplates, updateRegistry, true, pipelineLayout);
4334         }
4335         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4336         {
4337             writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4338                                updateBuilder, descriptorsPerSet, updateMethod);
4339         }
4340         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4341 #endif
4342         {
4343             writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet,
4344                                updateBuilder, descriptorsPerSet);
4345         }
4346 
4347         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
4348     }
4349     return descriptorSets;
4350 }
4351 
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)4352 void ImageFetchRenderInstance::writeDescriptorSet(
4353     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4354     ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4355     vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4356     vk::DescriptorSetUpdateBuilder &updateBuilder, std::vector<uint32_t> &descriptorsPerSet,
4357     DescriptorUpdateMethod updateMethod)
4358 {
4359     DE_UNREF(layout);
4360     DE_UNREF(pool);
4361     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(descriptorType);
4362     const vk::VkDescriptorImageInfo imageInfos[2] = {
4363         makeDescriptorImageInfo(viewA, imageLayout),
4364         makeDescriptorImageInfo(viewB, imageLayout),
4365     };
4366     uint32_t numDescriptors = 0u;
4367 
4368     switch (shaderInterface)
4369     {
4370     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4371         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4372                                   &imageInfos[0]);
4373         numDescriptors++;
4374         break;
4375 
4376     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4377         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4378                                   &imageInfos[0]);
4379         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType,
4380                                   &imageInfos[1]);
4381         numDescriptors += 2;
4382         break;
4383 
4384     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4385         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4386                                   &imageInfos[0]);
4387         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), descriptorType,
4388                                   &imageInfos[1]);
4389         numDescriptors += 2;
4390         break;
4391 
4392     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4393         updateBuilder.writeSingle(descriptorSet,
4394                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4395                                   descriptorType, &imageInfos[0]);
4396         updateBuilder.writeSingle(descriptorSet,
4397                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4398                                   descriptorType, &imageInfos[1]);
4399         numDescriptors += 2;
4400         break;
4401 
4402     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4403         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
4404                                  2u, imageInfos);
4405         numDescriptors++;
4406         break;
4407 
4408     default:
4409         DE_FATAL("Impossible");
4410     }
4411 
4412     descriptorsPerSet.push_back(numDescriptors);
4413 
4414     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4415     {
4416         updateBuilder.update(vki, device);
4417         updateBuilder.clear();
4418     }
4419 }
4420 
4421 #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)4422 void ImageFetchRenderInstance::writeDescriptorSetWithTemplate(
4423     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
4424     ShaderInputInterface shaderInterface, vk::VkDescriptorSetLayout layout, vk::VkDescriptorPool pool,
4425     vk::VkImageView viewA, vk::VkImageView viewB, vk::VkDescriptorSet descriptorSet,
4426     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
4427     vk::VkPipelineLayout pipelineLayout)
4428 {
4429     DE_UNREF(pool);
4430     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4431     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4432         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4433         nullptr,
4434         0,
4435         0,       // updateCount
4436         nullptr, // pUpdates
4437         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4438                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4439         layout,
4440         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4441         pipelineLayout,
4442         0};
4443     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(descriptorType);
4444     const vk::VkDescriptorImageInfo imageInfos[2] = {
4445         makeDescriptorImageInfo(viewA, imageLayout),
4446         makeDescriptorImageInfo(viewB, imageLayout),
4447     };
4448 
4449     RawUpdateRegistry updateRegistry;
4450 
4451     updateRegistry.addWriteObject(imageInfos[0]);
4452     updateRegistry.addWriteObject(imageInfos[1]);
4453 
4454     switch (shaderInterface)
4455     {
4456     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4457         updateEntries.push_back(
4458             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4459         break;
4460 
4461     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4462         updateEntries.push_back(
4463             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4464         updateEntries.push_back(
4465             createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4466         break;
4467 
4468     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4469         updateEntries.push_back(
4470             createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0));
4471         updateEntries.push_back(
4472             createTemplateBinding(2, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0));
4473         break;
4474 
4475     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4476         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, descriptorType,
4477                                                       updateRegistry.getWriteObjectOffset(0), 0));
4478         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, descriptorType,
4479                                                       updateRegistry.getWriteObjectOffset(1), 0));
4480         break;
4481 
4482     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4483         updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0),
4484                                                       sizeof(imageInfos[0])));
4485         break;
4486 
4487     default:
4488         DE_FATAL("Impossible");
4489     }
4490 
4491     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
4492     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
4493 
4494     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
4495         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
4496     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
4497     registry.push_back(updateRegistry);
4498 
4499     if (!withPush)
4500     {
4501         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
4502                                             registry.back().getRawPointer());
4503     }
4504 }
4505 #endif
4506 
logTestPlan(void) const4507 void ImageFetchRenderInstance::logTestPlan(void) const
4508 {
4509     std::ostringstream msg;
4510 
4511     msg << "Rendering 2x2 grid.\n"
4512         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
4513                                                                     "Multiple descriptor sets. ")
4514         << "Each descriptor set contains "
4515         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
4516             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
4517             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
4518             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
4519             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
4520                                                                                      nullptr)
4521         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
4522         << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4523 
4524     if (m_baseMipLevel)
4525         msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4526     if (m_baseArraySlice)
4527         msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4528 
4529     if (m_stageFlags == 0u)
4530     {
4531         msg << "Descriptors are not accessed in any shader stage.\n";
4532     }
4533     else
4534     {
4535         msg << "Color in each cell is fetched using the descriptor(s):\n";
4536 
4537         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4538         {
4539             msg << "Test sample " << resultNdx << ": fetching at position "
4540                 << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4541 
4542             if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4543             {
4544                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4545                 msg << " from descriptor " << srcResourceNdx;
4546             }
4547 
4548             msg << "\n";
4549         }
4550 
4551         msg << "Descriptors are accessed in {"
4552             << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : (""))
4553             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : (""))
4554             << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : (""))
4555             << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : (""))
4556             << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) << " } stages.";
4557     }
4558 
4559     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
4560 }
4561 
getPipelineLayout(void) const4562 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout(void) const
4563 {
4564     return *m_pipelineLayout;
4565 }
4566 
writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const4567 void ImageFetchRenderInstance::writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const
4568 {
4569     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE &&
4570         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4571     {
4572         std::vector<vk::VkDescriptorSet> sets;
4573         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4574             sets.push_back(**m_descriptorSets[setNdx]);
4575 
4576         switch (m_descriptorSetCount)
4577         {
4578         case DESCRIPTOR_SET_COUNT_SINGLE:
4579         case DESCRIPTOR_SET_COUNT_MULTIPLE:
4580         {
4581             bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4582                                getPipelineLayout(), 0, (int)sets.size(), &sets.front(), 0, nullptr, m_bind2);
4583             break;
4584         }
4585         case DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS:
4586         {
4587             for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4588             {
4589                 const uint32_t descriptorSetNdx = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
4590                 bindDescriptorSets(m_vki, cmd, m_stageFlags, m_existingStages, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
4591                                    getPipelineLayout(), descriptorSetNdx, 1, &sets[setNdx], 0, nullptr, m_bind2);
4592             }
4593             break;
4594         }
4595         default:
4596             DE_FATAL("Impossible");
4597         }
4598     }
4599 #ifndef CTS_USES_VULKANSC
4600     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4601     {
4602         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4603             m_vki.cmdPushDescriptorSetWithTemplate(cmd, **m_updateTemplates[setNdx], getPipelineLayout(),
4604                                                    getDescriptorSetNdx(m_descriptorSetCount, setNdx),
4605                                                    (const void *)m_updateRegistry[setNdx].getRawPointer());
4606     }
4607     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4608     {
4609         uint32_t descriptorNdx = 0u;
4610         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
4611         {
4612             const uint32_t numDescriptors = m_descriptorsPerSet[setNdx];
4613             m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout,
4614                                            getDescriptorSetNdx(m_descriptorSetCount, setNdx), descriptorNdx,
4615                                            numDescriptors);
4616             descriptorNdx += numDescriptors;
4617         }
4618     }
4619 #endif
4620 
4621     m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
4622 }
4623 
verifyResultImage(const tcu::ConstPixelBufferAccess & result) const4624 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage(const tcu::ConstPixelBufferAccess &result) const
4625 {
4626     const uint32_t numDescriptorSets = getDescriptorSetCount(m_descriptorSetCount);
4627     const tcu::Vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
4628     const tcu::Vec4 yellow(1.0f, 1.0f, 0.0f, 1.0f);
4629     const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch
4630 
4631     tcu::Surface reference(m_targetSize.x(), m_targetSize.y());
4632 
4633     tcu::Vec4 sample0 = tcu::Vec4(0.0f);
4634     tcu::Vec4 sample1 = tcu::Vec4(0.0f);
4635     tcu::Vec4 sample2 = tcu::Vec4(0.0f);
4636     tcu::Vec4 sample3 = tcu::Vec4(0.0f);
4637 
4638     for (uint32_t setNdx = 0; setNdx < numDescriptorSets; setNdx++)
4639     {
4640         sample0 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(0, setNdx));
4641         sample1 += (!doFetch) ? (green) : (m_images.fetchImageValue(1, setNdx));
4642         sample2 += (!doFetch) ? (green) : (m_images.fetchImageValue(2, setNdx));
4643         sample3 += (!doFetch) ? (yellow) : (m_images.fetchImageValue(3, setNdx));
4644     }
4645 
4646     if (numDescriptorSets > 1)
4647     {
4648         sample0 = sample0 / tcu::Vec4(float(numDescriptorSets));
4649         sample1 = sample1 / tcu::Vec4(float(numDescriptorSets));
4650         sample2 = sample2 / tcu::Vec4(float(numDescriptorSets));
4651         sample3 = sample3 / tcu::Vec4(float(numDescriptorSets));
4652     }
4653 
4654     drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4655 
4656     if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(),
4657                          result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
4658         return tcu::TestStatus::fail("Image verification failed");
4659     else
4660         return tcu::TestStatus::pass("Pass");
4661 }
4662 
4663 class ImageFetchComputeInstance : public vkt::TestInstance
4664 {
4665 public:
4666     ImageFetchComputeInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod,
4667                               vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
4668                               ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
4669                               uint32_t baseArraySlice, const bool bind2);
4670 
4671 private:
4672     vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout(uint32_t setNdx) const;
4673     vk::Move<vk::VkDescriptorPool> createDescriptorPool(void) const;
4674     vk::Move<vk::VkDescriptorSet> createDescriptorSet(vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout,
4675                                                       uint32_t setNdx);
4676     void writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx);
4677 #ifndef CTS_USES_VULKANSC
4678     void writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout,
4679                                         uint32_t setNdx, bool withPush = false,
4680                                         vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
4681 #endif
4682 
4683     tcu::TestStatus iterate(void);
4684     void logTestPlan(void) const;
4685     tcu::TestStatus testResourceAccess(void);
4686 
4687     const DescriptorUpdateMethod m_updateMethod;
4688     const vk::VkDescriptorType m_descriptorType;
4689     const DescriptorSetCount m_descriptorSetCount;
4690     const ShaderInputInterface m_shaderInterface;
4691     const vk::VkImageViewType m_viewType;
4692     const uint32_t m_numLevels;
4693     const uint32_t m_baseMipLevel;
4694     const uint32_t m_baseArraySlice;
4695     const bool m_bind2;
4696 #ifndef CTS_USES_VULKANSC
4697     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
4698 #endif
4699     const vk::DeviceInterface &m_vki;
4700     const vk::VkDevice m_device;
4701     const vk::VkQueue m_queue;
4702     const uint32_t m_queueFamilyIndex;
4703     vk::Allocator &m_allocator;
4704     const ComputeInstanceResultBuffer m_result;
4705     const ImageFetchInstanceImages m_images;
4706 #ifndef CTS_USES_VULKANSC
4707     std::vector<RawUpdateRegistry> m_updateRegistry;
4708 #endif
4709     vk::DescriptorSetUpdateBuilder m_updateBuilder;
4710     std::vector<uint32_t> m_descriptorsPerSet;
4711 };
4712 
ImageFetchComputeInstance(Context & context,DescriptorUpdateMethod updateMethod,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,const bool bind2)4713 ImageFetchComputeInstance::ImageFetchComputeInstance(Context &context, DescriptorUpdateMethod updateMethod,
4714                                                      vk::VkDescriptorType descriptorType,
4715                                                      DescriptorSetCount descriptorSetCount,
4716                                                      ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
4717                                                      uint32_t baseMipLevel, uint32_t baseArraySlice, const bool bind2)
4718     : vkt::TestInstance(context)
4719     , m_updateMethod(updateMethod)
4720     , m_descriptorType(descriptorType)
4721     , m_descriptorSetCount(descriptorSetCount)
4722     , m_shaderInterface(shaderInterface)
4723     , m_viewType(viewType)
4724     , m_numLevels(baseMipLevel + 1u)
4725     , m_baseMipLevel(baseMipLevel)
4726     , m_baseArraySlice(baseArraySlice)
4727     , m_bind2(bind2)
4728 #ifndef CTS_USES_VULKANSC
4729     , m_updateTemplates()
4730 #endif
4731     , m_vki(context.getDeviceInterface())
4732     , m_device(context.getDevice())
4733     , m_queue(context.getUniversalQueue())
4734     , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
4735     , m_allocator(context.getDefaultAllocator())
4736     , m_result(m_vki, m_device, m_allocator)
4737     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
4738                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice)
4739 #ifndef CTS_USES_VULKANSC
4740     , m_updateRegistry()
4741 #endif
4742     , m_updateBuilder()
4743     , m_descriptorsPerSet()
4744 {
4745 }
4746 
createDescriptorSetLayout(uint32_t setNdx) const4747 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout(uint32_t setNdx) const
4748 {
4749     vk::DescriptorSetLayoutBuilder builder;
4750     vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
4751     uint32_t binding                                = 0;
4752 
4753 #ifndef CTS_USES_VULKANSC
4754     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
4755         m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
4756     {
4757         extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
4758     }
4759 #endif
4760 
4761     if (setNdx == 0)
4762         builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT,
4763                                         binding++);
4764 
4765     switch (m_shaderInterface)
4766     {
4767     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4768         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4769         break;
4770 
4771     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4772         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4773         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4774         break;
4775 
4776     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4777         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding);
4778         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding + 2);
4779         break;
4780 
4781     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4782         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(0));
4783         builder.addSingleIndexedBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, getArbitraryBindingIndex(1));
4784         break;
4785 
4786     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4787         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4788         break;
4789 
4790     default:
4791         DE_FATAL("Impossible");
4792     }
4793 
4794     return builder.build(m_vki, m_device, extraFlags);
4795 }
4796 
createDescriptorPool(void) const4797 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool(void) const
4798 {
4799     return vk::DescriptorPoolBuilder()
4800         .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
4801         .addType(m_descriptorType,
4802                  getDescriptorSetCount(m_descriptorSetCount) * getInterfaceNumResources(m_shaderInterface))
4803         .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
4804                getDescriptorSetCount(m_descriptorSetCount));
4805 }
4806 
createDescriptorSet(vk::VkDescriptorPool pool,vk::VkDescriptorSetLayout layout,uint32_t setNdx)4807 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet(vk::VkDescriptorPool pool,
4808                                                                              vk::VkDescriptorSetLayout layout,
4809                                                                              uint32_t setNdx)
4810 {
4811     const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
4812                                                        pool, 1u, &layout};
4813 
4814     vk::Move<vk::VkDescriptorSet> descriptorSet;
4815     if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
4816         m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
4817     {
4818         descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo);
4819     }
4820     else
4821     {
4822         descriptorSet = vk::Move<vk::VkDescriptorSet>();
4823     }
4824 
4825 #ifndef CTS_USES_VULKANSC
4826     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
4827     {
4828         writeDescriptorSetWithTemplate(*descriptorSet, layout, setNdx);
4829     }
4830     else
4831 #endif
4832         if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4833     {
4834         writeDescriptorSet(*descriptorSet, setNdx);
4835     }
4836 
4837     return descriptorSet;
4838 }
4839 
writeDescriptorSet(vk::VkDescriptorSet descriptorSet,uint32_t setNdx)4840 void ImageFetchComputeInstance::writeDescriptorSet(vk::VkDescriptorSet descriptorSet, uint32_t setNdx)
4841 {
4842     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4843         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4844     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(m_descriptorType);
4845     const vk::VkDescriptorImageInfo imageInfos[2] = {
4846         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4847                                 imageLayout),
4848         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4849                                 imageLayout),
4850     };
4851 
4852     uint32_t binding        = 0u;
4853     uint32_t numDescriptors = 0u;
4854 
4855     // result
4856     if (setNdx == 0)
4857     {
4858         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4859                                     vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4860         numDescriptors++;
4861     }
4862 
4863     // images
4864     switch (m_shaderInterface)
4865     {
4866     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4867         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4868                                     m_descriptorType, &imageInfos[0]);
4869         numDescriptors++;
4870         break;
4871 
4872     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4873         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4874                                     m_descriptorType, &imageInfos[0]);
4875         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4876                                     m_descriptorType, &imageInfos[1]);
4877         numDescriptors += 2;
4878         break;
4879 
4880     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4881         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding),
4882                                     m_descriptorType, &imageInfos[0]);
4883         m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding + 2),
4884                                     m_descriptorType, &imageInfos[1]);
4885         numDescriptors += 2;
4886         break;
4887 
4888     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4889         m_updateBuilder.writeSingle(descriptorSet,
4890                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
4891                                     m_descriptorType, &imageInfos[0]);
4892         m_updateBuilder.writeSingle(descriptorSet,
4893                                     vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
4894                                     m_descriptorType, &imageInfos[1]);
4895         numDescriptors += 2;
4896         break;
4897 
4898     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4899         m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(binding++),
4900                                    m_descriptorType, 2u, imageInfos);
4901         numDescriptors++;
4902         break;
4903 
4904     default:
4905         DE_FATAL("Impossible");
4906     }
4907 
4908     m_descriptorsPerSet.push_back(numDescriptors);
4909 
4910     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
4911     {
4912         m_updateBuilder.update(m_vki, m_device);
4913         m_updateBuilder.clear();
4914     }
4915 }
4916 
4917 #ifndef CTS_USES_VULKANSC
writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,vk::VkDescriptorSetLayout layout,uint32_t setNdx,bool withPush,vk::VkPipelineLayout pipelineLayout)4918 void ImageFetchComputeInstance::writeDescriptorSetWithTemplate(vk::VkDescriptorSet descriptorSet,
4919                                                                vk::VkDescriptorSetLayout layout, uint32_t setNdx,
4920                                                                bool withPush, vk::VkPipelineLayout pipelineLayout)
4921 {
4922     const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(
4923         m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4924     const vk::VkImageLayout imageLayout           = getImageLayoutForDescriptorType(m_descriptorType);
4925     const vk::VkDescriptorImageInfo imageInfos[2] = {
4926         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface)),
4927                                 imageLayout),
4928         makeDescriptorImageInfo(m_images.getImageView(setNdx * getInterfaceNumResources(m_shaderInterface) + 1),
4929                                 imageLayout),
4930     };
4931     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
4932     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
4933         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
4934         nullptr,
4935         0,
4936         0,       // updateCount
4937         nullptr, // pUpdates
4938         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
4939                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
4940         layout,
4941         vk::VK_PIPELINE_BIND_POINT_COMPUTE,
4942         pipelineLayout,
4943         setNdx};
4944 
4945     uint32_t binding = 0u;
4946     uint32_t offset  = 0u;
4947     RawUpdateRegistry updateRegistry;
4948 
4949     if (setNdx == 0)
4950         updateRegistry.addWriteObject(resultInfo);
4951 
4952     updateRegistry.addWriteObject(imageInfos[0]);
4953     updateRegistry.addWriteObject(imageInfos[1]);
4954 
4955     // result
4956     if (setNdx == 0)
4957         updateEntries.push_back(createTemplateBinding(binding++, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
4958                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4959 
4960     // images
4961     switch (m_shaderInterface)
4962     {
4963     case SHADER_INPUT_SINGLE_DESCRIPTOR:
4964         updateEntries.push_back(
4965             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4966         break;
4967 
4968     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
4969         updateEntries.push_back(
4970             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4971         updateEntries.push_back(
4972             createTemplateBinding(binding++, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4973         break;
4974 
4975     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
4976         updateEntries.push_back(
4977             createTemplateBinding(binding, 0, 1, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), 0));
4978         updateEntries.push_back(createTemplateBinding(binding + 2, 0, 1, m_descriptorType,
4979                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4980         break;
4981 
4982     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
4983         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1, m_descriptorType,
4984                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4985         updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1, m_descriptorType,
4986                                                       updateRegistry.getWriteObjectOffset(offset++), 0));
4987         break;
4988 
4989     case SHADER_INPUT_DESCRIPTOR_ARRAY:
4990         updateEntries.push_back(createTemplateBinding(
4991             binding++, 0, 2, m_descriptorType, updateRegistry.getWriteObjectOffset(offset++), sizeof(imageInfos[0])));
4992         break;
4993 
4994     default:
4995         DE_FATAL("Impossible");
4996     }
4997 
4998     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
4999     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
5000 
5001     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
5002         vk::createDescriptorUpdateTemplate(m_vki, m_device, &templateCreateInfo);
5003     m_updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
5004     m_updateRegistry.push_back(updateRegistry);
5005 
5006     if (!withPush)
5007     {
5008         m_vki.updateDescriptorSetWithTemplate(m_device, descriptorSet, **m_updateTemplates.back(),
5009                                               m_updateRegistry.back().getRawPointer());
5010     }
5011 }
5012 #endif
5013 
iterate(void)5014 tcu::TestStatus ImageFetchComputeInstance::iterate(void)
5015 {
5016     logTestPlan();
5017     return testResourceAccess();
5018 }
5019 
logTestPlan(void) const5020 void ImageFetchComputeInstance::logTestPlan(void) const
5021 {
5022     std::ostringstream msg;
5023 
5024     msg << "Fetching 4 values from image in compute shader.\n"
5025         << ((m_descriptorSetCount == DESCRIPTOR_SET_COUNT_SINGLE) ? "Single descriptor set. " :
5026                                                                     "Multiple descriptor sets. ")
5027         << "Each descriptor set contains "
5028         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? "single" :
5029             (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? "two" :
5030             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" :
5031             (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? "two" :
5032             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)                   ? "an array (size 2) of" :
5033                                                                                      nullptr)
5034         << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5035         << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
5036 
5037     if (m_baseMipLevel)
5038         msg << "Image view base mip level = " << m_baseMipLevel << "\n";
5039     if (m_baseArraySlice)
5040         msg << "Image view base array slice = " << m_baseArraySlice << "\n";
5041 
5042     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5043     {
5044         msg << "Test sample " << resultNdx << ": fetch at position "
5045             << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
5046 
5047         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5048         {
5049             const int srcResourceNdx = (resultNdx % 2); // ABAB source
5050             msg << " from descriptor " << srcResourceNdx;
5051         }
5052 
5053         msg << "\n";
5054     }
5055 
5056     m_context.getTestContext().getLog() << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
5057 }
5058 
testResourceAccess(void)5059 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess(void)
5060 {
5061     const vk::Unique<vk::VkDescriptorPool> descriptorPool(createDescriptorPool());
5062     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5063     std::vector<DescriptorSetHandleSp> descriptorSets;
5064     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5065     std::vector<vk::VkDescriptorSet> setHandles;
5066 
5067     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5068     {
5069         vk::Move<vk::VkDescriptorSetLayout> layout = createDescriptorSetLayout(setNdx);
5070         vk::Move<vk::VkDescriptorSet> set          = createDescriptorSet(*descriptorPool, *layout, setNdx);
5071 
5072         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5073         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(set)));
5074 
5075         layoutHandles.push_back(**descriptorSetLayouts.back());
5076         setHandles.push_back(**descriptorSets.back());
5077 
5078         // Add an empty descriptor set layout between sets 0 and 2
5079         if (setNdx == 0 && m_descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5080         {
5081             vk::DescriptorSetLayoutBuilder emptyBuilder;
5082             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5083                 emptyBuilder.build(m_vki, m_device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5084 
5085             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5086             layoutHandles.push_back(**descriptorSetLayouts.back());
5087         }
5088     }
5089 
5090     const ComputePipeline pipeline(m_vki, m_device, m_context.getBinaryCollection(), (int)layoutHandles.size(),
5091                                    &layoutHandles.front());
5092     const uint32_t *const dynamicOffsets                = nullptr;
5093     const int numDynamicOffsets                         = 0;
5094     const vk::VkBufferMemoryBarrier *const preBarriers  = nullptr;
5095     const int numPreBarriers                            = 0;
5096     const vk::VkBufferMemoryBarrier *const postBarriers = m_result.getResultReadBarrier();
5097     const int numPostBarriers                           = 1;
5098 
5099     const ComputeCommand compute(m_vki, m_device, pipeline.getPipeline(), pipeline.getPipelineLayout(),
5100                                  tcu::UVec3(4, 1, 1), m_shaderInterface, m_descriptorSetCount, &setHandles.front(),
5101                                  numDynamicOffsets, dynamicOffsets, numPreBarriers, preBarriers, numPostBarriers,
5102                                  postBarriers, m_bind2);
5103 
5104     tcu::Vec4 results[4];
5105     bool anyResultSet = false;
5106     bool allResultsOk = true;
5107 
5108 #ifndef CTS_USES_VULKANSC
5109     if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5110     {
5111         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5112             writeDescriptorSetWithTemplate(VK_NULL_HANDLE, layoutHandles[setNdx], setNdx, true,
5113                                            pipeline.getPipelineLayout());
5114 
5115         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
5116     }
5117     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5118     {
5119         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5120             writeDescriptorSet(VK_NULL_HANDLE, setNdx);
5121 
5122         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
5123     }
5124     else
5125 #endif
5126     {
5127         compute.submitAndWait(m_queueFamilyIndex, m_queue);
5128     }
5129     m_result.readResultContentsTo(&results);
5130 
5131     // verify
5132     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5133     {
5134         const tcu::Vec4 result = results[resultNdx];
5135 
5136         tcu::Vec4 reference = tcu::Vec4(0.0f);
5137         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
5138             reference += m_images.fetchImageValue(resultNdx, setNdx);
5139 
5140         if (getDescriptorSetCount(m_descriptorSetCount) > 1)
5141             reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
5142 
5143         const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
5144 
5145         if (result != tcu::Vec4(-1.0f))
5146             anyResultSet = true;
5147 
5148         if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5149         {
5150             allResultsOk = false;
5151 
5152             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
5153                                                 << reference << ", got " << result << tcu::TestLog::EndMessage;
5154         }
5155     }
5156 
5157     // read back and verify
5158     if (allResultsOk)
5159         return tcu::TestStatus::pass("Pass");
5160     else if (anyResultSet)
5161         return tcu::TestStatus::fail("Invalid result values");
5162     else
5163     {
5164         m_context.getTestContext().getLog()
5165             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
5166         return tcu::TestStatus::fail("Result buffer was not written to");
5167     }
5168 }
5169 
5170 class ImageSampleInstanceImages : private ImageInstanceImages
5171 {
5172 public:
5173     ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device, uint32_t queueFamilyIndex,
5174                               vk::VkQueue queue, vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5175                               DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5176                               vk::VkImageViewType viewType, uint32_t numLevels, uint32_t baseMipLevel,
5177                               uint32_t baseArraySlice, bool immutable);
5178 
5179     static std::vector<tcu::Sampler> getRefSamplers(DescriptorSetCount descriptorSetCount,
5180                                                     ShaderInputInterface shaderInterface);
5181 
5182     static std::vector<SamplerHandleSp> getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5183                                                     std::vector<tcu::Sampler> &refSamplers,
5184                                                     const tcu::TextureFormat imageFormat);
5185 
5186     static tcu::Vec4 getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel, uint32_t baseArraySlice,
5187                                   int samplePosNdx);
5188     tcu::Vec4 fetchSampleValue(int samplePosNdx, int setNdx) const;
5189 
getSourceImage(int ndx) const5190     inline tcu::TextureLevelPyramid getSourceImage(int ndx) const
5191     {
5192         return m_sourceImage[ndx % m_sourceImage.size()];
5193     }
getImageView(int ndx) const5194     inline vk::VkImageView getImageView(int ndx) const
5195     {
5196         return **m_imageView[ndx % m_imageView.size()];
5197     }
getRefSampler(int ndx) const5198     inline tcu::Sampler getRefSampler(int ndx) const
5199     {
5200         return m_refSampler[ndx % m_refSampler.size()];
5201     }
getSampler(int ndx) const5202     inline vk::VkSampler getSampler(int ndx) const
5203     {
5204         return **m_sampler[ndx % m_sampler.size()];
5205     }
isImmutable(void) const5206     inline bool isImmutable(void) const
5207     {
5208         return m_isImmutable;
5209     }
5210 
5211 private:
5212     static int getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5213                             ShaderInputInterface shaderInterface);
5214     static tcu::Sampler createRefSampler(int ndx);
5215     static vk::Move<vk::VkSampler> createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5216                                                  const tcu::Sampler &sampler, const tcu::TextureFormat &format);
5217 
5218     static tcu::Texture1DArrayView getRef1DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5219                                                 uint32_t baseArraySlice,
5220                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5221     static tcu::Texture2DArrayView getRef2DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5222                                                 uint32_t baseArraySlice,
5223                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5224     static tcu::Texture3DView getRef3DView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5225                                            uint32_t baseArraySlice,
5226                                            std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5227     static tcu::TextureCubeArrayView getRefCubeView(const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel,
5228                                                     uint32_t baseArraySlice,
5229                                                     std::vector<tcu::ConstPixelBufferAccess> *levelStorage);
5230 
5231     const vk::VkDescriptorType m_descriptorType;
5232     const ShaderInputInterface m_shaderInterface;
5233     const bool m_isImmutable;
5234 
5235     std::vector<tcu::Sampler> m_refSampler;
5236     std::vector<SamplerHandleSp> m_sampler;
5237 };
5238 
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)5239 ImageSampleInstanceImages::ImageSampleInstanceImages(const vk::DeviceInterface &vki, vk::VkDevice device,
5240                                                      uint32_t queueFamilyIndex, vk::VkQueue queue,
5241                                                      vk::Allocator &allocator, vk::VkDescriptorType descriptorType,
5242                                                      DescriptorSetCount descriptorSetCount,
5243                                                      ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5244                                                      uint32_t numLevels, uint32_t baseMipLevel, uint32_t baseArraySlice,
5245                                                      bool immutable)
5246     : ImageInstanceImages(vki, device, queueFamilyIndex, queue, allocator, descriptorType, viewType,
5247                           getNumImages(descriptorType, descriptorSetCount, shaderInterface), numLevels, baseMipLevel,
5248                           baseArraySlice)
5249     , m_descriptorType(descriptorType)
5250     , m_shaderInterface(shaderInterface)
5251     , m_isImmutable(immutable)
5252     , m_refSampler(getRefSamplers(descriptorSetCount, shaderInterface))
5253     , m_sampler(getSamplers(vki, device, m_refSampler, m_imageFormat))
5254 {
5255 }
5256 
getRefSamplers(DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5257 std::vector<tcu::Sampler> ImageSampleInstanceImages::getRefSamplers(DescriptorSetCount descriptorSetCount,
5258                                                                     ShaderInputInterface shaderInterface)
5259 {
5260     std::vector<tcu::Sampler> refSamplers;
5261     for (uint32_t samplerNdx = 0;
5262          samplerNdx < getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface);
5263          samplerNdx++)
5264         refSamplers.push_back(createRefSampler(samplerNdx));
5265 
5266     return refSamplers;
5267 }
5268 
getSamplers(const vk::DeviceInterface & vki,vk::VkDevice device,std::vector<tcu::Sampler> & refSamplers,const tcu::TextureFormat imageFormat)5269 std::vector<SamplerHandleSp> ImageSampleInstanceImages::getSamplers(const vk::DeviceInterface &vki, vk::VkDevice device,
5270                                                                     std::vector<tcu::Sampler> &refSamplers,
5271                                                                     const tcu::TextureFormat imageFormat)
5272 {
5273     std::vector<SamplerHandleSp> samplers;
5274     for (uint32_t samplerNdx = 0; samplerNdx < (uint32_t)refSamplers.size(); samplerNdx++)
5275     {
5276         vk::Move<vk::VkSampler> sampler = createSampler(vki, device, refSamplers[samplerNdx], imageFormat);
5277         samplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
5278     }
5279     return samplers;
5280 }
5281 
getSamplePos(vk::VkImageViewType viewType,uint32_t baseMipLevel,uint32_t baseArraySlice,int samplePosNdx)5282 tcu::Vec4 ImageSampleInstanceImages::getSamplePos(vk::VkImageViewType viewType, uint32_t baseMipLevel,
5283                                                   uint32_t baseArraySlice, int samplePosNdx)
5284 {
5285     DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5286 
5287     const uint32_t imageSize = (uint32_t)IMAGE_SIZE >> baseMipLevel;
5288     const uint32_t arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
5289 
5290     // choose arbitrary values that are not ambiguous with NEAREST filtering
5291 
5292     switch (viewType)
5293     {
5294     case vk::VK_IMAGE_VIEW_TYPE_1D:
5295     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5296     case vk::VK_IMAGE_VIEW_TYPE_2D:
5297     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5298     case vk::VK_IMAGE_VIEW_TYPE_3D:
5299     {
5300         const tcu::Vec3 coords[4] = {
5301             tcu::Vec3(0.75f, 0.5f, (float)(12u % imageSize) + 0.25f),
5302 
5303             tcu::Vec3((float)(23u % imageSize) + 0.25f, (float)(73u % imageSize) + 0.5f,
5304                       (float)(16u % imageSize) + 0.5f + (float)imageSize),
5305 
5306             tcu::Vec3(-(float)(43u % imageSize) + 0.25f, (float)(84u % imageSize) + 0.5f + (float)imageSize,
5307                       (float)(117u % imageSize) + 0.75f),
5308 
5309             tcu::Vec3((float)imageSize + 0.5f, (float)(75u % imageSize) + 0.25f,
5310                       (float)(83u % imageSize) + 0.25f + (float)imageSize),
5311         };
5312         const uint32_t slices[4] = {
5313             0u % arraySize,
5314             4u % arraySize,
5315             9u % arraySize,
5316             2u % arraySize,
5317         };
5318 
5319         switch (viewType)
5320         {
5321         case vk::VK_IMAGE_VIEW_TYPE_1D:
5322         case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5323             return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, (float)slices[samplePosNdx], 0.0f, 0.0f);
5324         case vk::VK_IMAGE_VIEW_TYPE_2D:
5325         case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5326             return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5327                              (float)slices[samplePosNdx], 0.0f);
5328         case vk::VK_IMAGE_VIEW_TYPE_3D:
5329             return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, coords[samplePosNdx].y() / (float)imageSize,
5330                              coords[samplePosNdx].z() / (float)imageSize, 0.0f);
5331         default:
5332             DE_FATAL("Impossible");
5333             return tcu::Vec4();
5334         }
5335     }
5336 
5337     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5338     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5339     {
5340         // \note these values are in [0, texSize]*3 space for convenience
5341         const tcu::Vec3 coords[4] = {
5342             tcu::Vec3(0.75f, 0.5f, (float)imageSize),
5343 
5344             tcu::Vec3((float)(13u % imageSize) + 0.25f, 0.0f, (float)(16u % imageSize) + 0.5f),
5345 
5346             tcu::Vec3(0.0f, (float)(84u % imageSize) + 0.5f, (float)(10u % imageSize) + 0.75f),
5347 
5348             tcu::Vec3((float)imageSize, (float)(75u % imageSize) + 0.25f, (float)(83u % imageSize) + 0.75f),
5349         };
5350         const uint32_t slices[4] = {
5351             1u % arraySize,
5352             2u % arraySize,
5353             9u % arraySize,
5354             5u % arraySize,
5355         };
5356 
5357         DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
5358         DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
5359         DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
5360 
5361         // map to [-1, 1]*3 space
5362         return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
5363                          coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
5364                          coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f, (float)slices[samplePosNdx]);
5365     }
5366 
5367     default:
5368         DE_FATAL("Impossible");
5369         return tcu::Vec4();
5370     }
5371 }
5372 
fetchSampleValue(int samplePosNdx,int setNdx) const5373 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue(int samplePosNdx, int setNdx) const
5374 {
5375     DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
5376 
5377     // texture order is ABAB
5378     const bool isSamplerCase                   = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
5379     const uint32_t numImages                   = (isSamplerCase) ? 1 : getInterfaceNumResources(m_shaderInterface);
5380     const tcu::TextureLevelPyramid &sampleSrcA = getSourceImage(setNdx * numImages);
5381     const tcu::TextureLevelPyramid &sampleSrcB =
5382         (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? sampleSrcA : getSourceImage(setNdx * numImages + 1);
5383     const tcu::TextureLevelPyramid &sampleSrc = (isSamplerCase)           ? (sampleSrcA) :
5384                                                 ((samplePosNdx % 2) == 0) ? (sampleSrcA) :
5385                                                                             (sampleSrcB);
5386 
5387     // sampler order is ABAB
5388     const tcu::Sampler &samplerA = getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface));
5389     const tcu::Sampler &samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ?
5390                                        (samplerA) :
5391                                        getRefSampler(setNdx * getInterfaceNumResources(m_shaderInterface) + 1);
5392     const tcu::Sampler &sampler  = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
5393 
5394     const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5395     const float lod           = 0.0f;
5396     std::vector<tcu::ConstPixelBufferAccess> levelStorage;
5397 
5398     switch (m_viewType)
5399     {
5400     case vk::VK_IMAGE_VIEW_TYPE_1D:
5401     case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
5402         return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5403             .sample(sampler, samplePos.x(), samplePos.y(), lod);
5404     case vk::VK_IMAGE_VIEW_TYPE_2D:
5405     case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
5406         return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5407             .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5408     case vk::VK_IMAGE_VIEW_TYPE_3D:
5409         return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5410             .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
5411     case vk::VK_IMAGE_VIEW_TYPE_CUBE:
5412     case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
5413         return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage)
5414             .sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod);
5415 
5416     default:
5417     {
5418         DE_FATAL("Impossible");
5419         return tcu::Vec4();
5420     }
5421     }
5422 }
5423 
getNumImages(vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5424 int ImageSampleInstanceImages::getNumImages(vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5425                                             ShaderInputInterface shaderInterface)
5426 {
5427     // If we are testing separate samplers, just one image is enough
5428     if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5429         return getDescriptorSetCount(descriptorSetCount);
5430     else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5431     {
5432         // combined: numImages == numSamplers
5433         return getInterfaceNumResources(shaderInterface) * getDescriptorSetCount(descriptorSetCount);
5434     }
5435     else
5436     {
5437         DE_FATAL("Impossible");
5438         return 0;
5439     }
5440 }
5441 
createRefSampler(int ndx)5442 tcu::Sampler ImageSampleInstanceImages::createRefSampler(int ndx)
5443 {
5444     if (ndx % 2 == 0)
5445     {
5446         // linear, wrapping
5447         return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
5448                             tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5449                             tcu::Vec4(0.0f), true);
5450     }
5451     else
5452     {
5453         // nearest, clamping
5454         return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
5455                             tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0,
5456                             tcu::Vec4(0.0f), true);
5457     }
5458 }
5459 
createSampler(const vk::DeviceInterface & vki,vk::VkDevice device,const tcu::Sampler & sampler,const tcu::TextureFormat & format)5460 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler(const vk::DeviceInterface &vki, vk::VkDevice device,
5461                                                                  const tcu::Sampler &sampler,
5462                                                                  const tcu::TextureFormat &format)
5463 {
5464     const vk::VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, format);
5465 
5466     return vk::createSampler(vki, device, &createInfo);
5467 }
5468 
getRef1DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5469 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView(const tcu::TextureLevelPyramid &source,
5470                                                                 uint32_t baseMipLevel, uint32_t baseArraySlice,
5471                                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5472 {
5473     DE_ASSERT(levelStorage->empty());
5474 
5475     const uint32_t numSlices = (uint32_t)source.getLevel(0).getHeight();
5476     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5477 
5478     // cut pyramid from baseMipLevel
5479     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5480     {
5481         // cut levels from baseArraySlice
5482         const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5483         const tcu::ConstPixelBufferAccess cutLevel =
5484             tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
5485         levelStorage->push_back(cutLevel);
5486     }
5487 
5488     return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
5489 }
5490 
getRef2DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5491 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView(const tcu::TextureLevelPyramid &source,
5492                                                                 uint32_t baseMipLevel, uint32_t baseArraySlice,
5493                                                                 std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5494 {
5495     DE_ASSERT(levelStorage->empty());
5496 
5497     const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth();
5498     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5499 
5500     // cut pyramid from baseMipLevel
5501     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5502     {
5503         // cut levels from baseArraySlice
5504         const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5505         const tcu::ConstPixelBufferAccess cutLevel =
5506             tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(),
5507                               numSlices - baseArraySlice);
5508         levelStorage->push_back(cutLevel);
5509     }
5510 
5511     return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
5512 }
5513 
getRef3DView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5514 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView(const tcu::TextureLevelPyramid &source,
5515                                                            uint32_t baseMipLevel, uint32_t baseArraySlice,
5516                                                            std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5517 {
5518     DE_ASSERT(levelStorage->empty());
5519     DE_ASSERT(baseArraySlice == 0);
5520     DE_UNREF(baseArraySlice);
5521 
5522     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5523 
5524     // cut pyramid from baseMipLevel
5525     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5526         levelStorage->push_back(source.getLevel(level));
5527 
5528     return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
5529 }
5530 
getRefCubeView(const tcu::TextureLevelPyramid & source,uint32_t baseMipLevel,uint32_t baseArraySlice,std::vector<tcu::ConstPixelBufferAccess> * levelStorage)5531 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView(
5532     const tcu::TextureLevelPyramid &source, uint32_t baseMipLevel, uint32_t baseArraySlice,
5533     std::vector<tcu::ConstPixelBufferAccess> *levelStorage)
5534 {
5535     DE_ASSERT(levelStorage->empty());
5536 
5537     const uint32_t numSlices = (uint32_t)source.getLevel(0).getDepth() / 6;
5538     const uint32_t numLevels = (uint32_t)source.getNumLevels();
5539 
5540     // cut pyramid from baseMipLevel
5541     for (uint32_t level = baseMipLevel; level < numLevels; ++level)
5542     {
5543         // cut levels from baseArraySlice
5544         const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level);
5545         const tcu::ConstPixelBufferAccess cutLevel =
5546             tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(),
5547                               (numSlices - baseArraySlice) * 6);
5548         levelStorage->push_back(cutLevel);
5549     }
5550 
5551     return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
5552 }
5553 
5554 class ImageSampleRenderInstance : public SingleCmdRenderInstance
5555 {
5556 public:
5557     ImageSampleRenderInstance(vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5558                               vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5559                               vk::VkShaderStageFlags stageFlags, vk::VkShaderStageFlags existingStages,
5560                               ShaderInputInterface shaderInterface, vk::VkImageViewType viewType, uint32_t baseMipLevel,
5561                               uint32_t baseArraySlice, bool isImmutable, const bool bind2);
5562 
5563 private:
5564     static std::vector<DescriptorSetLayoutHandleSp> createDescriptorSetLayouts(
5565         const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5566         DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5567         const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod);
5568 
5569     static vk::Move<vk::VkPipelineLayout> createPipelineLayout(
5570         const vk::DeviceInterface &vki, vk::VkDevice device,
5571         const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout);
5572 
5573     static vk::Move<vk::VkDescriptorPool> createDescriptorPool(const vk::DeviceInterface &vki, vk::VkDevice device,
5574                                                                vk::VkDescriptorType descriptorType,
5575                                                                DescriptorSetCount descriptorSetCount,
5576                                                                ShaderInputInterface shaderInterface);
5577 
5578     static std::vector<DescriptorSetHandleSp> createDescriptorSets(
5579         const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5580         vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount,
5581         ShaderInputInterface shaderInterface, const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts,
5582         vk::VkDescriptorPool pool, bool isImmutable, const ImageSampleInstanceImages &images,
5583         vk::DescriptorSetUpdateBuilder &updateBuilder,
5584 #ifndef CTS_USES_VULKANSC
5585         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5586 #endif
5587         std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
5588 
5589     static void writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5590                                           ShaderInputInterface shaderInterface, bool isImmutable,
5591                                           const ImageSampleInstanceImages &images, vk::VkDescriptorSet descriptorSet,
5592                                           uint32_t setNdx, vk::DescriptorSetUpdateBuilder &updateBuilder,
5593                                           std::vector<uint32_t> &descriptorsPerSet,
5594                                           DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5595 
5596     static void writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5597                                                ShaderInputInterface shaderInterface, bool isImmutable,
5598                                                const ImageSampleInstanceImages &images,
5599                                                vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5600                                                vk::DescriptorSetUpdateBuilder &updateBuilder,
5601                                                std::vector<uint32_t> &descriptorsPerSet,
5602                                                DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL);
5603 
5604     static void writeSamplerDescriptorSetWithTemplate(
5605         const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5606         ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5607         vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5608 #ifndef CTS_USES_VULKANSC
5609         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry,
5610 #endif
5611         bool withPush = false, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
5612 
5613     static void writeImageSamplerDescriptorSetWithTemplate(
5614         const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
5615         ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
5616         vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
5617 #ifndef CTS_USES_VULKANSC
5618         std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry,
5619 #endif
5620         bool withPush = false, vk::VkPipelineLayout pipelineLayout = VK_NULL_HANDLE);
5621 
5622     void logTestPlan(void) const;
5623     vk::VkPipelineLayout getPipelineLayout(void) const;
5624     void writeDrawCmdBuffer(vk::VkCommandBuffer cmd) const;
5625     tcu::TestStatus verifyResultImage(const tcu::ConstPixelBufferAccess &result) const;
5626 
5627     enum
5628     {
5629         RENDER_SIZE = 128,
5630     };
5631 
5632     const DescriptorUpdateMethod m_updateMethod;
5633     const vk::VkDescriptorType m_descriptorType;
5634     const DescriptorSetCount m_descriptorSetCount;
5635     const vk::VkShaderStageFlags m_stageFlags;
5636     const vk::VkShaderStageFlags m_existingStages;
5637     const ShaderInputInterface m_shaderInterface;
5638     const vk::VkImageViewType m_viewType;
5639     const uint32_t m_numLevels;
5640     const uint32_t m_baseMipLevel;
5641     const uint32_t m_baseArraySlice;
5642 
5643 #ifndef CTS_USES_VULKANSC
5644     std::vector<UpdateTemplateHandleSp> m_updateTemplates;
5645     std::vector<RawUpdateRegistry> m_updateRegistry;
5646 #endif
5647     vk::DescriptorSetUpdateBuilder m_updateBuilder;
5648     const ImageSampleInstanceImages m_images;
5649     std::vector<uint32_t> m_descriptorsPerSet;
5650     const std::vector<DescriptorSetLayoutHandleSp> m_descriptorSetLayouts;
5651     const vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
5652     const vk::Unique<vk::VkDescriptorPool> m_descriptorPool;
5653     const std::vector<DescriptorSetHandleSp> m_descriptorSets;
5654 };
5655 
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)5656 ImageSampleRenderInstance::ImageSampleRenderInstance(
5657     vkt::Context &context, DescriptorUpdateMethod updateMethod, bool isPrimaryCmdBuf,
5658     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, vk::VkShaderStageFlags stageFlags,
5659     vk::VkShaderStageFlags existingStages, ShaderInputInterface shaderInterface, vk::VkImageViewType viewType,
5660     uint32_t baseMipLevel, uint32_t baseArraySlice, bool isImmutable, const bool bind2)
5661     : SingleCmdRenderInstance(context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE), bind2)
5662     , m_updateMethod(updateMethod)
5663     , m_descriptorType(descriptorType)
5664     , m_descriptorSetCount(descriptorSetCount)
5665     , m_stageFlags(stageFlags)
5666     , m_existingStages(existingStages)
5667     , m_shaderInterface(shaderInterface)
5668     , m_viewType(viewType)
5669     , m_numLevels(baseMipLevel + 1u)
5670     , m_baseMipLevel(baseMipLevel)
5671     , m_baseArraySlice(baseArraySlice)
5672 #ifndef CTS_USES_VULKANSC
5673     , m_updateTemplates()
5674     , m_updateRegistry()
5675 #endif
5676     , m_updateBuilder()
5677     , m_images(m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_descriptorSetCount,
5678                m_shaderInterface, m_viewType, m_numLevels, m_baseMipLevel, m_baseArraySlice, isImmutable)
5679     , m_descriptorSetLayouts(createDescriptorSetLayouts(m_vki, m_device, m_descriptorType, m_descriptorSetCount,
5680                                                         m_shaderInterface, m_stageFlags, m_images, m_updateMethod))
5681     , m_pipelineLayout(createPipelineLayout(m_vki, m_device, m_descriptorSetLayouts))
5682     , m_descriptorPool(createDescriptorPool(m_vki, m_device, m_descriptorType, m_descriptorSetCount, m_shaderInterface))
5683     , m_descriptorSets(createDescriptorSets(m_vki, m_updateMethod, m_device, m_descriptorType, m_descriptorSetCount,
5684                                             m_shaderInterface, m_descriptorSetLayouts, *m_descriptorPool, isImmutable,
5685                                             m_images, m_updateBuilder,
5686 #ifndef CTS_USES_VULKANSC
5687                                             m_updateTemplates, m_updateRegistry,
5688 #endif
5689                                             m_descriptorsPerSet, *m_pipelineLayout))
5690 {
5691 }
5692 
createDescriptorSetLayouts(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface,vk::VkShaderStageFlags stageFlags,const ImageSampleInstanceImages & images,DescriptorUpdateMethod updateMethod)5693 std::vector<DescriptorSetLayoutHandleSp> ImageSampleRenderInstance::createDescriptorSetLayouts(
5694     const vk::DeviceInterface &vki, vk::VkDevice device, vk::VkDescriptorType descriptorType,
5695     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, vk::VkShaderStageFlags stageFlags,
5696     const ImageSampleInstanceImages &images, DescriptorUpdateMethod updateMethod)
5697 {
5698 #ifdef CTS_USES_VULKANSC
5699     DE_UNREF(updateMethod);
5700 #endif
5701     std::vector<DescriptorSetLayoutHandleSp> descriptorSetLayouts;
5702 
5703     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5704     {
5705         const vk::VkSampler samplers[2] = {
5706             images.getSampler(setNdx * getInterfaceNumResources(shaderInterface)),
5707             images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1),
5708         };
5709 
5710         vk::DescriptorSetLayoutBuilder builder;
5711         const bool addSeparateImage                     = descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER;
5712         vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0;
5713 
5714 #ifndef CTS_USES_VULKANSC
5715         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE ||
5716             updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5717         {
5718             extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
5719         }
5720 #endif
5721 
5722         // (combined)samplers follow
5723         switch (shaderInterface)
5724         {
5725         case SHADER_INPUT_SINGLE_DESCRIPTOR:
5726             if (addSeparateImage)
5727                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5728             builder.addSingleSamplerBinding(descriptorType, stageFlags,
5729                                             (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5730             break;
5731 
5732         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5733             if (addSeparateImage)
5734                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5735             builder.addSingleSamplerBinding(descriptorType, stageFlags,
5736                                             (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5737             builder.addSingleSamplerBinding(descriptorType, stageFlags,
5738                                             (images.isImmutable()) ? (&samplers[1]) : (nullptr));
5739             break;
5740 
5741         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5742             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 0u,
5743                                                    (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5744             if (addSeparateImage)
5745                 builder.addSingleIndexedBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags, 1u);
5746             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, 2u,
5747                                                    (images.isImmutable()) ? (&samplers[1]) : (nullptr));
5748             break;
5749 
5750         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5751             if (addSeparateImage)
5752                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5753             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(0),
5754                                                    (images.isImmutable()) ? (&samplers[0]) : (nullptr));
5755             builder.addSingleIndexedSamplerBinding(descriptorType, stageFlags, getArbitraryBindingIndex(1),
5756                                                    (images.isImmutable()) ? (&samplers[1]) : (nullptr));
5757             break;
5758 
5759         case SHADER_INPUT_DESCRIPTOR_ARRAY:
5760             if (addSeparateImage)
5761                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
5762             builder.addArraySamplerBinding(descriptorType, 2u, stageFlags,
5763                                            (images.isImmutable()) ? (samplers) : (nullptr));
5764             break;
5765 
5766         default:
5767             DE_FATAL("Impossible");
5768         }
5769 
5770         vk::Move<vk::VkDescriptorSetLayout> layout = builder.build(vki, device, extraFlags);
5771         descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(layout)));
5772 
5773         // Add an empty descriptor set layout between sets 0 and 2
5774         if (setNdx == 0 && descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS)
5775         {
5776             vk::DescriptorSetLayoutBuilder emptyBuilder;
5777             vk::Move<vk::VkDescriptorSetLayout> emptyLayout =
5778                 emptyBuilder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0);
5779             descriptorSetLayouts.push_back(DescriptorSetLayoutHandleSp(new DescriptorSetLayoutHandleUp(emptyLayout)));
5780         }
5781     }
5782 
5783     return descriptorSetLayouts;
5784 }
5785 
createPipelineLayout(const vk::DeviceInterface & vki,vk::VkDevice device,const std::vector<DescriptorSetLayoutHandleSp> & descriptorSetLayout)5786 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout(
5787     const vk::DeviceInterface &vki, vk::VkDevice device,
5788     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayout)
5789 {
5790     std::vector<vk::VkDescriptorSetLayout> layoutHandles;
5791     for (size_t setNdx = 0; setNdx < descriptorSetLayout.size(); setNdx++)
5792         layoutHandles.push_back(**descriptorSetLayout[setNdx]);
5793 
5794     const vk::VkPipelineLayoutCreateInfo createInfo = {
5795         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5796         nullptr,
5797         (vk::VkPipelineLayoutCreateFlags)0,
5798         (uint32_t)layoutHandles.size(), // descriptorSetCount
5799         &layoutHandles.front(),         // pSetLayouts
5800         0u,                             // pushConstantRangeCount
5801         nullptr,                        // pPushConstantRanges
5802     };
5803     return vk::createPipelineLayout(vki, device, &createInfo);
5804 }
5805 
createDescriptorPool(const vk::DeviceInterface & vki,vk::VkDevice device,vk::VkDescriptorType descriptorType,DescriptorSetCount descriptorSetCount,ShaderInputInterface shaderInterface)5806 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool(const vk::DeviceInterface &vki,
5807                                                                                vk::VkDevice device,
5808                                                                                vk::VkDescriptorType descriptorType,
5809                                                                                DescriptorSetCount descriptorSetCount,
5810                                                                                ShaderInputInterface shaderInterface)
5811 {
5812     vk::DescriptorPoolBuilder builder;
5813 
5814     if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5815     {
5816         // separate samplers need image to sample
5817         builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, getDescriptorSetCount(descriptorSetCount));
5818 
5819         // also need sample to use, indifferent of whether immutable or not
5820         builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER,
5821                         getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5822     }
5823     else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5824     {
5825         // combined image samplers
5826         builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
5827                         getDescriptorSetCount(descriptorSetCount) * getInterfaceNumResources(shaderInterface));
5828     }
5829     else
5830         DE_FATAL("Impossible");
5831 
5832     return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
5833                          getDescriptorSetCount(descriptorSetCount));
5834 }
5835 
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)5836 std::vector<DescriptorSetHandleSp> ImageSampleRenderInstance::createDescriptorSets(
5837     const vk::DeviceInterface &vki, DescriptorUpdateMethod updateMethod, vk::VkDevice device,
5838     vk::VkDescriptorType descriptorType, DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
5839     const std::vector<DescriptorSetLayoutHandleSp> &descriptorSetLayouts, vk::VkDescriptorPool pool, bool isImmutable,
5840     const ImageSampleInstanceImages &images, vk::DescriptorSetUpdateBuilder &updateBuilder,
5841 #ifndef CTS_USES_VULKANSC
5842     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &updateRegistry,
5843 #endif
5844     std::vector<uint32_t> &descriptorsPerSet, vk::VkPipelineLayout pipelineLayout)
5845 {
5846 #ifdef CTS_USES_VULKANSC
5847     DE_UNREF(pipelineLayout);
5848 #endif
5849     std::vector<DescriptorSetHandleSp> descriptorSets;
5850 
5851     for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(descriptorSetCount); setNdx++)
5852     {
5853         vk::VkDescriptorSetLayout layout = **descriptorSetLayouts[getDescriptorSetNdx(descriptorSetCount, setNdx)];
5854 
5855         const vk::VkDescriptorSetAllocateInfo allocInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr,
5856                                                            pool, 1u, &layout};
5857 
5858         vk::Move<vk::VkDescriptorSet> descriptorSet;
5859         if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH &&
5860             updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5861         {
5862             descriptorSet = allocateDescriptorSet(vki, device, &allocInfo);
5863         }
5864         else
5865         {
5866             descriptorSet = vk::Move<vk::VkDescriptorSet>();
5867         }
5868 
5869 #ifndef CTS_USES_VULKANSC
5870         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE)
5871         {
5872             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5873                 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5874                                                       images, *descriptorSet, setNdx, layout, updateTemplates,
5875                                                       updateRegistry);
5876             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5877                 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5878                                                            isImmutable, images, *descriptorSet, setNdx, layout,
5879                                                            updateTemplates, updateRegistry);
5880             else
5881                 DE_FATAL("Impossible");
5882         }
5883         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
5884         {
5885             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5886                 writeSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface, isImmutable,
5887                                                       images, VK_NULL_HANDLE, setNdx, layout, updateTemplates,
5888                                                       updateRegistry, true, pipelineLayout);
5889             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5890                 writeImageSamplerDescriptorSetWithTemplate(vki, device, descriptorSetCount, shaderInterface,
5891                                                            isImmutable, images, VK_NULL_HANDLE, setNdx, layout,
5892                                                            updateTemplates, updateRegistry, true, pipelineLayout);
5893             else
5894                 DE_FATAL("Impossible");
5895         }
5896         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
5897         {
5898             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5899                 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5900                                           updateBuilder, descriptorsPerSet, updateMethod);
5901             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5902                 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5903                                                setNdx, updateBuilder, descriptorsPerSet, updateMethod);
5904             else
5905                 DE_FATAL("Impossible");
5906         }
5907         else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
5908 #endif
5909         {
5910             if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5911                 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, setNdx,
5912                                           updateBuilder, descriptorsPerSet);
5913             else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
5914                 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet,
5915                                                setNdx, updateBuilder, descriptorsPerSet);
5916             else
5917                 DE_FATAL("Impossible");
5918         }
5919 
5920         descriptorSets.push_back(DescriptorSetHandleSp(new DescriptorSetHandleUp(descriptorSet)));
5921     }
5922     return descriptorSets;
5923 }
5924 
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)5925 void ImageSampleRenderInstance::writeSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
5926                                                           ShaderInputInterface shaderInterface, bool isImmutable,
5927                                                           const ImageSampleInstanceImages &images,
5928                                                           vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
5929                                                           vk::DescriptorSetUpdateBuilder &updateBuilder,
5930                                                           std::vector<uint32_t> &descriptorsPerSet,
5931                                                           DescriptorUpdateMethod updateMethod)
5932 {
5933     const vk::VkDescriptorImageInfo imageInfo =
5934         makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
5935     vk::VkDescriptorImageInfo samplersInfos[2] = {
5936         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
5937         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
5938     };
5939 
5940     if (isImmutable)
5941     {
5942         samplersInfos[0].sampler = VK_NULL_HANDLE;
5943         samplersInfos[1].sampler = VK_NULL_HANDLE;
5944     }
5945 
5946     const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
5947     uint32_t numDescriptors        = 1u;
5948 
5949     // stand alone texture
5950     updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation),
5951                               vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
5952 
5953     // samplers
5954     if (!isImmutable || (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH))
5955     {
5956         switch (shaderInterface)
5957         {
5958         case SHADER_INPUT_SINGLE_DESCRIPTOR:
5959             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5960                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5961             numDescriptors++;
5962             break;
5963 
5964         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
5965             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5966                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5967             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5968                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5969             numDescriptors += 2;
5970             break;
5971 
5972         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
5973             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
5974                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5975             updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
5976                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5977             numDescriptors += 2;
5978             break;
5979 
5980         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
5981             updateBuilder.writeSingle(descriptorSet,
5982                                       vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
5983                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
5984             updateBuilder.writeSingle(descriptorSet,
5985                                       vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
5986                                       vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
5987             numDescriptors += 2;
5988             break;
5989 
5990         case SHADER_INPUT_DESCRIPTOR_ARRAY:
5991             updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
5992                                      vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
5993             numDescriptors++;
5994             break;
5995 
5996         default:
5997             DE_FATAL("Impossible");
5998         }
5999     }
6000 
6001     descriptorsPerSet.push_back(numDescriptors);
6002 
6003     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6004     {
6005         updateBuilder.update(vki, device);
6006         updateBuilder.clear();
6007     }
6008 }
6009 
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)6010 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet(const vk::DeviceInterface &vki, vk::VkDevice device,
6011                                                                ShaderInputInterface shaderInterface, bool isImmutable,
6012                                                                const ImageSampleInstanceImages &images,
6013                                                                vk::VkDescriptorSet descriptorSet, uint32_t setNdx,
6014                                                                vk::DescriptorSetUpdateBuilder &updateBuilder,
6015                                                                std::vector<uint32_t> &descriptorsPerSet,
6016                                                                DescriptorUpdateMethod updateMethod)
6017 {
6018     const vk::VkSampler samplers[2] = {
6019         (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6020             VK_NULL_HANDLE :
6021             (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6022         (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ?
6023             VK_NULL_HANDLE :
6024             (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6025     };
6026     const vk::VkDescriptorImageInfo imageSamplers[2] = {
6027         vk::makeDescriptorImageInfo(samplers[0],
6028                                     images.getImageView(setNdx * getInterfaceNumResources(shaderInterface)),
6029                                     vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6030         vk::makeDescriptorImageInfo(samplers[1],
6031                                     images.getImageView(setNdx * getInterfaceNumResources(shaderInterface) + 1),
6032                                     vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
6033     };
6034     uint32_t numDescriptors = 0u;
6035 
6036     // combined image samplers
6037     switch (shaderInterface)
6038     {
6039     case SHADER_INPUT_SINGLE_DESCRIPTOR:
6040         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6041                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6042         numDescriptors++;
6043         break;
6044 
6045     case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6046         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6047                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6048         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u),
6049                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6050         numDescriptors += 2;
6051         break;
6052 
6053     case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6054         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6055                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6056         updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u),
6057                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6058         numDescriptors += 2;
6059         break;
6060 
6061     case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6062         updateBuilder.writeSingle(descriptorSet,
6063                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(0)),
6064                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
6065         updateBuilder.writeSingle(descriptorSet,
6066                                   vk::DescriptorSetUpdateBuilder::Location::binding(getArbitraryBindingIndex(1)),
6067                                   vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
6068         numDescriptors += 2;
6069         break;
6070 
6071     case SHADER_INPUT_DESCRIPTOR_ARRAY:
6072         updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
6073                                  vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
6074         numDescriptors++;
6075         break;
6076 
6077     default:
6078         DE_FATAL("Impossible");
6079     }
6080 
6081     descriptorsPerSet.push_back(numDescriptors);
6082 
6083     if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL)
6084     {
6085         updateBuilder.update(vki, device);
6086         updateBuilder.clear();
6087     }
6088 }
6089 
6090 #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)6091 void ImageSampleRenderInstance::writeSamplerDescriptorSetWithTemplate(
6092     const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6093     ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6094     vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6095     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
6096     vk::VkPipelineLayout pipelineLayout)
6097 {
6098     const vk::VkDescriptorImageInfo imageInfo =
6099         makeDescriptorImageInfo(images.getImageView(setNdx), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
6100     const vk::VkDescriptorImageInfo samplersInfos[2] = {
6101         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6102         makeDescriptorImageInfo(images.getSampler(setNdx * getInterfaceNumResources(shaderInterface) + 1)),
6103     };
6104 
6105     const uint32_t samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u;
6106 
6107     std::vector<vk::VkDescriptorUpdateTemplateEntry> updateEntries;
6108     vk::VkDescriptorUpdateTemplateCreateInfo templateCreateInfo = {
6109         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR,
6110         nullptr,
6111         0,
6112         0,       // updateCount
6113         nullptr, // pUpdates
6114         withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR :
6115                    vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
6116         layout,
6117         vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
6118         pipelineLayout,
6119         getDescriptorSetNdx(descriptorSetCount, setNdx)};
6120 
6121     RawUpdateRegistry updateRegistry;
6122 
6123     updateRegistry.addWriteObject(imageInfo);
6124     updateRegistry.addWriteObject(samplersInfos[0]);
6125     updateRegistry.addWriteObject(samplersInfos[1]);
6126 
6127     // stand alone texture
6128     updateEntries.push_back(createTemplateBinding(samplerLocation, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6129                                                   updateRegistry.getWriteObjectOffset(0), 0));
6130 
6131     // samplers
6132     if (!isImmutable || withPush)
6133     {
6134         switch (shaderInterface)
6135         {
6136         case SHADER_INPUT_SINGLE_DESCRIPTOR:
6137             updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6138                                                           updateRegistry.getWriteObjectOffset(1), 0));
6139             break;
6140 
6141         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
6142             updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6143                                                           updateRegistry.getWriteObjectOffset(1), 0));
6144             updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6145                                                           updateRegistry.getWriteObjectOffset(2), 0));
6146             break;
6147 
6148         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
6149             updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6150                                                           updateRegistry.getWriteObjectOffset(1), 0));
6151             updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6152                                                           updateRegistry.getWriteObjectOffset(2), 0));
6153             break;
6154 
6155         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
6156             updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(0), 0, 1,
6157                                                           vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6158                                                           updateRegistry.getWriteObjectOffset(1), 0));
6159             updateEntries.push_back(createTemplateBinding(getArbitraryBindingIndex(1), 0, 1,
6160                                                           vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6161                                                           updateRegistry.getWriteObjectOffset(2), 0));
6162             break;
6163 
6164         case SHADER_INPUT_DESCRIPTOR_ARRAY:
6165             updateEntries.push_back(createTemplateBinding(1, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER,
6166                                                           updateRegistry.getWriteObjectOffset(1),
6167                                                           sizeof(samplersInfos[0])));
6168             break;
6169 
6170         default:
6171             DE_FATAL("Impossible");
6172         }
6173     }
6174 
6175     templateCreateInfo.pDescriptorUpdateEntries   = &updateEntries[0];
6176     templateCreateInfo.descriptorUpdateEntryCount = (uint32_t)updateEntries.size();
6177 
6178     vk::Move<vk::VkDescriptorUpdateTemplate> updateTemplate =
6179         vk::createDescriptorUpdateTemplate(vki, device, &templateCreateInfo);
6180     updateTemplates.push_back(UpdateTemplateHandleSp(new UpdateTemplateHandleUp(updateTemplate)));
6181     registry.push_back(updateRegistry);
6182 
6183     if (!withPush)
6184     {
6185         vki.updateDescriptorSetWithTemplate(device, descriptorSet, **updateTemplates.back(),
6186                                             registry.back().getRawPointer());
6187     }
6188 }
6189 
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)6190 void ImageSampleRenderInstance::writeImageSamplerDescriptorSetWithTemplate(
6191     const vk::DeviceInterface &vki, vk::VkDevice device, DescriptorSetCount descriptorSetCount,
6192     ShaderInputInterface shaderInterface, bool isImmutable, const ImageSampleInstanceImages &images,
6193     vk::VkDescriptorSet descriptorSet, uint32_t setNdx, vk::VkDescriptorSetLayout layout,
6194     std::vector<UpdateTemplateHandleSp> &updateTemplates, std::vector<RawUpdateRegistry> &registry, bool withPush,
6195     vk::VkPipelineLayout pipelineLayout)
6196 {
6197     const vk::VkSampler samplers[2] = {
6198         (isImmutable && !withPush) ? VK_NULL_HANDLE :
6199                                      (images.getSampler(setNdx * getInterfaceNumResources(shaderInterface))),
6200         (isImmutable && !withPush) ? VK_NULL_HANDLE :
6201                                      (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         nullptr,
6216         0,
6217         0,       // updateCount
6218         nullptr, // 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                                                                                          nullptr)
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                                                                                          nullptr)
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, nullptr,
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, nullptr,
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.cmdPushDescriptorSetWithTemplate(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 = VK_NULL_HANDLE);
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 = VK_NULL_HANDLE);
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 = VK_NULL_HANDLE);
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]) : (nullptr));
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]) : (nullptr));
6617         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, binding++,
6618                                                (m_images.isImmutable()) ? (&samplers[1]) : (nullptr));
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]) : (nullptr));
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]) : (nullptr));
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]) : (nullptr));
6638         builder.addSingleIndexedSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT,
6639                                                getArbitraryBindingIndex(1),
6640                                                (m_images.isImmutable()) ? (&samplers[1]) : (nullptr));
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) : (nullptr));
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, nullptr,
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         nullptr,
6843         0,
6844         0,       // updateCount
6845         nullptr, // 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             VK_NULL_HANDLE :
6943             (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
6944         (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ?
6945             VK_NULL_HANDLE :
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             VK_NULL_HANDLE :
7033             (m_images.getSampler(setNdx * getInterfaceNumResources(m_shaderInterface))),
7034         (m_isImmutableSampler && !withPush) ?
7035             VK_NULL_HANDLE :
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         nullptr,
7049         0,
7050         0,       // updateCount
7051         nullptr, // 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                                                                                          nullptr)
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                                                                                          nullptr)
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                = nullptr;
7240     const int numDynamicOffsets                         = 0;
7241     const vk::VkBufferMemoryBarrier *const preBarriers  = nullptr;
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(VK_NULL_HANDLE, 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(VK_NULL_HANDLE, 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                                                                                                          (nullptr);
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                                                                                                          (nullptr);
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                                                                                            (nullptr);
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                                                                                               (nullptr);
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                                                                                               (nullptr);
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 nullptr;
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         nullptr,
8141         0u,                            // flags
8142         (vk::VkDeviceSize)BUFFER_SIZE, // size
8143         usage,                         // usage
8144         vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
8145         0u,                            // queueFamilyCount
8146         nullptr,                       // 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         nullptr,
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         nullptr,
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 = VK_NULL_HANDLE);
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 = VK_NULL_HANDLE);
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         nullptr,
8449         (vk::VkPipelineLayoutCreateFlags)0,
8450         (uint32_t)layoutHandles.size(), // descriptorSetCount
8451         &layoutHandles.front(),         // pSetLayouts
8452         0u,                             // pushConstantRangeCount
8453         nullptr,                        // 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, nullptr,
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         nullptr,
8622         0,
8623         0,       // updateCount
8624         nullptr, // 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                                                                                      nullptr)
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, nullptr, 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, nullptr, 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.cmdPushDescriptorSetWithTemplate(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 = VK_NULL_HANDLE);
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, nullptr,
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         nullptr,
9113         0,
9114         0,       // updateCount
9115         nullptr, // 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                                                                                      nullptr)
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                = nullptr;
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(VK_NULL_HANDLE, layoutHandles[setNdx], setNdx, true,
9286                                            pipeline.getPipelineLayout());
9287 
9288         compute.submitAndWait(m_queueFamilyIndex, m_queue, &m_updateTemplates, &m_updateRegistry);
9289     }
9290     else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)
9291     {
9292         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9293             writeDescriptorSet(VK_NULL_HANDLE, setNdx);
9294 
9295         compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder, m_descriptorsPerSet);
9296     }
9297     else
9298 #endif
9299     {
9300         compute.submitAndWait(m_queueFamilyIndex, m_queue);
9301     }
9302     m_result.readResultContentsTo(&results);
9303 
9304     // verify
9305     for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
9306     {
9307         const tcu::Vec4 result              = results[resultNdx];
9308         const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f);
9309 
9310         tcu::Vec4 reference = tcu::Vec4(0.0f);
9311         for (uint32_t setNdx = 0; setNdx < getDescriptorSetCount(m_descriptorSetCount); setNdx++)
9312             reference += m_texelBuffers.fetchTexelValue(resultNdx, setNdx);
9313 
9314         reference = reference / tcu::Vec4((float)getDescriptorSetCount(m_descriptorSetCount));
9315 
9316         if (result != tcu::Vec4(-1.0f))
9317             anyResultSet = true;
9318 
9319         if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
9320         {
9321             allResultsOk = false;
9322 
9323             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test sample " << resultNdx << ": Expected "
9324                                                 << reference << ", got " << result << tcu::TestLog::EndMessage;
9325         }
9326     }
9327 
9328     // read back and verify
9329     if (allResultsOk)
9330         return tcu::TestStatus::pass("Pass");
9331     else if (anyResultSet)
9332         return tcu::TestStatus::fail("Invalid result values");
9333     else
9334     {
9335         m_context.getTestContext().getLog()
9336             << tcu::TestLog::Message << "Result buffer was not written to." << tcu::TestLog::EndMessage;
9337         return tcu::TestStatus::fail("Result buffer was not written to");
9338     }
9339 }
9340 
9341 class TexelBufferDescriptorCase : public QuadrantRendederCase
9342 {
9343 public:
9344     enum
9345     {
9346         FLAG_VIEW_OFFSET = (1u << 1u),
9347     };
9348     // enum continues where resource flags ends
9349     DE_STATIC_ASSERT((uint32_t)FLAG_VIEW_OFFSET == (uint32_t)RESOURCE_FLAG_LAST);
9350 
9351     TexelBufferDescriptorCase(tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name,
9352                               bool isPrimaryCmdBuf, vk::VkDescriptorType descriptorType,
9353                               vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9354                               DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface,
9355                               uint32_t flags, const bool m_bind2);
9356 
9357     void checkSupport(Context &context) const;
9358 
9359 private:
9360     std::string genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const;
9361     std::string genResourceDeclarations(vk::VkShaderStageFlagBits stage, int numUsedBindings) const;
9362     std::string genResourceAccessSource(vk::VkShaderStageFlagBits stage) const;
9363     std::string genNoAccessSource(void) const;
9364 
9365     vkt::TestInstance *createInstance(vkt::Context &context) const;
9366 
9367     const DescriptorUpdateMethod m_updateMethod;
9368     const bool m_isPrimaryCmdBuf;
9369     const vk::VkDescriptorType m_descriptorType;
9370     const DescriptorSetCount m_descriptorSetCount;
9371     const ShaderInputInterface m_shaderInterface;
9372     const bool m_nonzeroViewOffset;
9373     const bool m_bind2;
9374 };
9375 
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)9376 TexelBufferDescriptorCase::TexelBufferDescriptorCase(
9377     tcu::TestContext &testCtx, DescriptorUpdateMethod updateMethod, const char *name, bool isPrimaryCmdBuf,
9378     vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9379     DescriptorSetCount descriptorSetCount, ShaderInputInterface shaderInterface, uint32_t flags, const bool bind2)
9380     : QuadrantRendederCase(testCtx, name, glu::GLSL_VERSION_310_ES, exitingStages, activeStages, descriptorSetCount)
9381     , m_updateMethod(updateMethod)
9382     , m_isPrimaryCmdBuf(isPrimaryCmdBuf)
9383     , m_descriptorType(descriptorType)
9384     , m_descriptorSetCount(descriptorSetCount)
9385     , m_shaderInterface(shaderInterface)
9386     , m_nonzeroViewOffset(((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
9387     , m_bind2(bind2)
9388 {
9389 }
9390 
checkSupport(Context & context) const9391 void TexelBufferDescriptorCase::checkSupport(Context &context) const
9392 {
9393     if (m_bind2)
9394         context.requireDeviceFunctionality("VK_KHR_maintenance6");
9395 }
9396 
genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const9397 std::string TexelBufferDescriptorCase::genExtensionDeclarations(vk::VkShaderStageFlagBits stage) const
9398 {
9399     DE_UNREF(stage);
9400     return "#extension GL_EXT_texture_buffer : require\n";
9401 }
9402 
genResourceDeclarations(vk::VkShaderStageFlagBits stage,int numUsedBindings) const9403 std::string TexelBufferDescriptorCase::genResourceDeclarations(vk::VkShaderStageFlagBits stage,
9404                                                                int numUsedBindings) const
9405 {
9406     DE_UNREF(stage);
9407 
9408     const bool isUniform              = isUniformDescriptorType(m_descriptorType);
9409     const char *const storageType     = (isUniform) ? ("textureBuffer ") : ("readonly imageBuffer ");
9410     const char *const formatQualifier = (isUniform) ? ("") : (", rgba8");
9411     const uint32_t numSets            = getDescriptorSetCount(m_descriptorSetCount);
9412 
9413     std::ostringstream buf;
9414 
9415     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9416     {
9417         // Result buffer is bound only to the first descriptor set in compute shader cases
9418         const int descBinding =
9419             numUsedBindings - ((m_activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) ? (setNdx == 0 ? 0 : 1) : 0);
9420         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9421         const uint32_t descriptorSet    = getDescriptorSetNdx(m_descriptorSetCount, setNdx);
9422 
9423         switch (m_shaderInterface)
9424         {
9425         case SHADER_INPUT_SINGLE_DESCRIPTOR:
9426             buf << "layout(set = " << descriptorSet
9427                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9428                        "u_texelBuffer"
9429                 << setNdxPostfix << ";\n";
9430             break;
9431         case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS:
9432             buf << "layout(set = " << descriptorSet
9433                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9434                        "u_texelBuffer"
9435                 << setNdxPostfix
9436                 << "A;\n"
9437                    "layout(set = "
9438                 << descriptorSet
9439                 << ", binding = " + de::toString(descBinding + 1) + formatQualifier + ") uniform highp " + storageType +
9440                        "u_texelBuffer"
9441                 << setNdxPostfix << "B;\n";
9442             break;
9443         case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS:
9444             buf << "layout(set = " << descriptorSet
9445                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9446                        "u_texelBuffer"
9447                 << setNdxPostfix
9448                 << "A;\n"
9449                    "layout(set = "
9450                 << descriptorSet
9451                 << ", binding = " + de::toString(descBinding + 2) + formatQualifier + ") uniform highp " + storageType +
9452                        "u_texelBuffer"
9453                 << setNdxPostfix << "B;\n";
9454             break;
9455         case SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS:
9456             buf << "layout(set = " << descriptorSet
9457                 << ", binding = " + de::toString(getArbitraryBindingIndex(0)) + formatQualifier + ") uniform highp " +
9458                        storageType + "u_texelBuffer"
9459                 << setNdxPostfix
9460                 << "A;\n"
9461                    "layout(set = "
9462                 << descriptorSet
9463                 << ", binding = " + de::toString(getArbitraryBindingIndex(1)) + formatQualifier + ") uniform highp " +
9464                        storageType + "u_texelBuffer"
9465                 << setNdxPostfix << "B;\n";
9466             break;
9467         case SHADER_INPUT_DESCRIPTOR_ARRAY:
9468             buf << "layout(set = " << descriptorSet
9469                 << ", binding = " + de::toString(descBinding) + formatQualifier + ") uniform highp " + storageType +
9470                        "u_texelBuffer"
9471                 << setNdxPostfix << "[2];\n";
9472             break;
9473         default:
9474             DE_FATAL("Impossible");
9475             return "";
9476         }
9477     }
9478     return buf.str();
9479 }
9480 
genResourceAccessSource(vk::VkShaderStageFlagBits stage) const9481 std::string TexelBufferDescriptorCase::genResourceAccessSource(vk::VkShaderStageFlagBits stage) const
9482 {
9483     DE_UNREF(stage);
9484 
9485     const char *const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? ("") :
9486                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? ("A") :
9487                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") :
9488                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? ("A") :
9489                                        (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") :
9490                                                                                               (nullptr);
9491     const char *const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)                  ? ("") :
9492                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS)    ? ("B") :
9493                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") :
9494                                        (m_shaderInterface == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS)     ? ("B") :
9495                                        (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") :
9496                                                                                               (nullptr);
9497     const char *const fetchFunc      = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
9498     const uint32_t numSets           = getDescriptorSetCount(m_descriptorSetCount);
9499 
9500     std::ostringstream buf;
9501 
9502     buf << "    result_color = vec4(0.0);\n";
9503 
9504     for (uint32_t setNdx = 0; setNdx < numSets; setNdx++)
9505     {
9506         const std::string setNdxPostfix = (numSets == 1) ? "" : de::toString(setNdx);
9507 
9508         buf << "    if (quadrant_id == 0)\n"
9509             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9510             << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
9511             << "    else if (quadrant_id == 1)\n"
9512             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9513             << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
9514             << "    else if (quadrant_id == 2)\n"
9515             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixA << ", "
9516             << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
9517             << "    else\n"
9518             << "        result_color += " << fetchFunc << "(u_texelBuffer" << setNdxPostfix << accessPostfixB << ", "
9519             << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
9520     }
9521 
9522     if (getDescriptorSetCount(m_descriptorSetCount) > 1)
9523         buf << "    result_color /= vec4(" << getDescriptorSetCount(m_descriptorSetCount) << ".0);\n";
9524 
9525     return buf.str();
9526 }
9527 
genNoAccessSource(void) const9528 std::string TexelBufferDescriptorCase::genNoAccessSource(void) const
9529 {
9530     return "    if (quadrant_id == 1 || quadrant_id == 2)\n"
9531            "        result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
9532            "    else\n"
9533            "        result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
9534 }
9535 
createInstance(vkt::Context & context) const9536 vkt::TestInstance *TexelBufferDescriptorCase::createInstance(vkt::Context &context) const
9537 {
9538     verifyDriverSupport(context.getUsedApiVersion(), context.getDeviceFeatures(), context.getDeviceExtensions(),
9539                         m_updateMethod, m_descriptorType, m_activeStages);
9540 
9541     if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
9542     {
9543         DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
9544         return new TexelBufferComputeInstance(context, m_updateMethod, m_descriptorType, m_descriptorSetCount,
9545                                               m_shaderInterface, m_nonzeroViewOffset, m_bind2);
9546     }
9547     else
9548         return new TexelBufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType,
9549                                              m_descriptorSetCount, m_activeStages, m_exitingStages, m_shaderInterface,
9550                                              m_nonzeroViewOffset, m_bind2);
9551 }
9552 
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)9553 void createShaderAccessImageTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9554                                   vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9555                                   vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9556                                   ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9557 {
9558     static const struct
9559     {
9560         vk::VkImageViewType viewType;
9561         const char *name;
9562         uint32_t flags;
9563     } s_imageTypes[] = {
9564         {vk::VK_IMAGE_VIEW_TYPE_1D, "1d", 0u},
9565         {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9566         {vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9567 
9568         {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", 0u},
9569         {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9570         {vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9571 
9572         {vk::VK_IMAGE_VIEW_TYPE_2D, "2d", 0u},
9573         {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9574         {vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9575 
9576         {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", 0u},
9577         {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9578         {vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9579 
9580         {vk::VK_IMAGE_VIEW_TYPE_3D, "3d", 0u},
9581         {vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9582         // no 3d array textures
9583 
9584         {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", 0u},
9585         {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9586         {vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE},
9587 
9588         {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", 0u},
9589         {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", ImageDescriptorCase::FLAG_BASE_MIP},
9590         {vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", ImageDescriptorCase::FLAG_BASE_SLICE}};
9591 
9592     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
9593     {
9594         // never overlap
9595         DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
9596 
9597         // skip some image view variations to avoid unnecessary bloating
9598         if ((descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER) &&
9599             (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9600             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9601             continue;
9602 
9603         if ((dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) &&
9604             (activeStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) &&
9605             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9606             continue;
9607 
9608         if ((dimension == SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS) &&
9609             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9610             continue;
9611 
9612         if ((descriptorSetCount == DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS) &&
9613             (s_imageTypes[ndx].viewType != vk::VK_IMAGE_VIEW_TYPE_2D))
9614             continue;
9615 
9616         group->addChild(new ImageDescriptorCase(group->getTestContext(), s_imageTypes[ndx].name, isPrimaryCmdBuf,
9617                                                 updateMethod, descriptorType, exitingStages, activeStages,
9618                                                 descriptorSetCount, dimension, s_imageTypes[ndx].viewType,
9619                                                 s_imageTypes[ndx].flags | resourceFlags, bind2));
9620     }
9621 }
9622 
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)9623 void createShaderAccessTexelBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9624                                         DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9625                                         vk::VkShaderStageFlags exitingStages, vk::VkShaderStageFlags activeStages,
9626                                         DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9627                                         uint32_t resourceFlags, const bool bind2)
9628 {
9629     DE_ASSERT(resourceFlags == 0);
9630     DE_UNREF(resourceFlags);
9631 
9632     static const struct
9633     {
9634         const char *name;
9635         uint32_t flags;
9636     } s_texelBufferTypes[] = {
9637         // View offset is zero
9638         {"offset_zero", 0u},
9639         // View offset is non-zero
9640         {"offset_nonzero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET},
9641     };
9642 
9643     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
9644     {
9645         group->addChild(new TexelBufferDescriptorCase(
9646             group->getTestContext(), updateMethod, s_texelBufferTypes[ndx].name, isPrimaryCmdBuf, descriptorType,
9647             exitingStages, activeStages, descriptorSetCount, dimension, s_texelBufferTypes[ndx].flags, bind2));
9648     }
9649 }
9650 
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)9651 void createShaderAccessBufferTests(tcu::TestCaseGroup *group, bool isPrimaryCmdBuf, DescriptorUpdateMethod updateMethod,
9652                                    vk::VkDescriptorType descriptorType, vk::VkShaderStageFlags exitingStages,
9653                                    vk::VkShaderStageFlags activeStages, DescriptorSetCount descriptorSetCount,
9654                                    ShaderInputInterface dimension, uint32_t resourceFlags, const bool bind2)
9655 {
9656     DE_ASSERT(resourceFlags == 0u);
9657     DE_UNREF(resourceFlags);
9658 
9659     static const struct
9660     {
9661         const char *name;
9662         bool isForDynamicCases;
9663         uint32_t flags;
9664     } s_bufferTypes[] = {
9665         {"offset_view_zero", false, 0u},
9666         {"offset_view_nonzero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET},
9667 
9668         {"offset_view_zero_dynamic_zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9669         {"offset_view_zero_dynamic_nonzero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9670         {"offset_view_nonzero_dynamic_zero", true,
9671          BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO},
9672         {"offset_view_nonzero_dynamic_nonzero", true,
9673          BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO},
9674     };
9675 
9676     const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
9677 
9678     if (isDynamicCase)
9679     {
9680         if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9681             updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9682         {
9683             // Can't support push descriptor sets with dynamic UBOs or SSBOs
9684             return;
9685         }
9686     }
9687 
9688     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
9689     {
9690         if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
9691             group->addChild(new BufferDescriptorCase(group->getTestContext(), updateMethod, s_bufferTypes[ndx].name,
9692                                                      isPrimaryCmdBuf, descriptorType, exitingStages, activeStages,
9693                                                      descriptorSetCount, dimension, s_bufferTypes[ndx].flags, bind2));
9694     }
9695 }
9696 
9697 } // namespace
9698 
createShaderAccessTests(tcu::TestContext & testCtx)9699 tcu::TestCaseGroup *createShaderAccessTests(tcu::TestContext &testCtx)
9700 {
9701     static const struct
9702     {
9703         const bool isPrimary;
9704         const char *name;
9705     } s_bindTypes[] = {
9706         // Bind in primary command buffer
9707         {true, "primary_cmd_buf"},
9708         // Bind in secondary command buffer
9709         {false, "secondary_cmd_buf"},
9710     };
9711     static const struct
9712     {
9713         const DescriptorUpdateMethod method;
9714         const char *name;
9715     } s_updateMethods[] = {
9716         {DESCRIPTOR_UPDATE_METHOD_NORMAL, ""},
9717 #ifndef CTS_USES_VULKANSC
9718         // Use descriptor update templates
9719         {DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, "with_template"},
9720         // Use push descriptor updates
9721         {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, "with_push"},
9722         // Use push descriptor update templates
9723         {DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, "with_push_template"},
9724 #endif
9725     };
9726     static const struct
9727     {
9728         const vk::VkDescriptorType descriptorType;
9729         const char *name;
9730         const char *description;
9731         uint32_t flags;
9732     } s_descriptorTypes[] = {
9733         {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u},
9734         {vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",
9735          RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9736         {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable",
9737          "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u},
9738         {vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable",
9739          "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER},
9740         // \note No way to access SAMPLED_IMAGE without a sampler
9741         //{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u                                },
9742         {vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u},
9743         {vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",
9744          0u},
9745         {vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",
9746          0u},
9747         {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u},
9748         {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u},
9749         {vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic",
9750          "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u},
9751         {vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic",
9752          "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u},
9753     };
9754     static const struct
9755     {
9756         const char *name;
9757         vk::VkShaderStageFlags existingStages; //!< stages that exists
9758         vk::VkShaderStageFlags activeStages;   //!< stages that access resource
9759         bool supportsSecondaryCmdBufs;
9760     } s_shaderStages[] = {
9761         // No accessing stages
9762         {
9763             "no_access",
9764             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9765             0u,
9766             true,
9767         },
9768         // Vertex stage
9769         {
9770             "vertex",
9771             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9772             vk::VK_SHADER_STAGE_VERTEX_BIT,
9773             true,
9774         },
9775         // Tessellation control stage
9776         {
9777             "tess_ctrl",
9778             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9779                 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9780             vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
9781             true,
9782         },
9783         // Tessellation evaluation stage
9784         {
9785             "tess_eval",
9786             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
9787                 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9788             vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
9789             true,
9790         },
9791         // Geometry stage
9792         {
9793             "geometry",
9794             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9795             vk::VK_SHADER_STAGE_GEOMETRY_BIT,
9796             true,
9797         },
9798         // Fragment stage
9799         {
9800             "fragment",
9801             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9802             vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9803             true,
9804         },
9805         // Compute stage
9806         {
9807             "compute",
9808             vk::VK_SHADER_STAGE_COMPUTE_BIT,
9809             vk::VK_SHADER_STAGE_COMPUTE_BIT,
9810             false,
9811         },
9812         // Vertex and fragment stages
9813         {
9814             "vertex_fragment",
9815             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9816             vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
9817             true,
9818         }};
9819     static const struct
9820     {
9821         ShaderInputInterface dimension;
9822         const char *name;
9823     } s_variableDimensions[] = {
9824         {SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor"},
9825         {SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, "multiple_contiguous_descriptors"},
9826         {SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, "multiple_discontiguous_descriptors"},
9827         {SHADER_INPUT_MULTIPLE_ARBITRARY_DESCRIPTORS, "multiple_arbitrary_descriptors"},
9828         {SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array"},
9829     };
9830     static const struct
9831     {
9832         const bool bind2;
9833         const char *name;
9834         const char *description;
9835     } s_bindCommand[] = {
9836         {false, "bind", "use_vkCmdBindDescriptors"},
9837         {true, "bind2", "use vkCmdBindDescriptors2"},
9838     };
9839 
9840     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access"));
9841 
9842     // .primary_cmd_buf...
9843     for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
9844     {
9845         de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name));
9846 
9847         for (int bindCommandNdx = 0; bindCommandNdx < DE_LENGTH_OF_ARRAY(s_bindCommand); ++bindCommandNdx)
9848         {
9849             de::MovePtr<tcu::TestCaseGroup> bindCommandGroup(
9850                 new tcu::TestCaseGroup(testCtx, s_bindCommand[bindCommandNdx].name));
9851 
9852             for (int updateMethodNdx = 0; updateMethodNdx < DE_LENGTH_OF_ARRAY(s_updateMethods); ++updateMethodNdx)
9853             {
9854                 de::MovePtr<tcu::TestCaseGroup> updateMethodGroup(
9855                     new tcu::TestCaseGroup(testCtx, s_updateMethods[updateMethodNdx].name));
9856 
9857                 // .sampler, .combined_image_sampler, other resource types ...
9858                 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
9859                 {
9860                     de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(
9861                         testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
9862 
9863                     for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
9864                     {
9865                         if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
9866                         {
9867                             de::MovePtr<tcu::TestCaseGroup> stageGroup(
9868                                 new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name));
9869                             de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(
9870                                 testCtx, "multiple_descriptor_sets", "Multiple descriptor sets"));
9871                             de::MovePtr<tcu::TestCaseGroup> multipleDiscontiguousGroup(
9872                                 new tcu::TestCaseGroup(testCtx, "multiple_discontiguous_descriptor_sets",
9873                                                        "Multiple discontiguous descriptor sets"));
9874 
9875                             for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions);
9876                                  ++dimensionNdx)
9877                             {
9878                                 de::MovePtr<tcu::TestCaseGroup> dimensionSingleDescriptorSetGroup(
9879                                     new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9880                                 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDescriptorSetsGroup(
9881                                     new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9882                                 de::MovePtr<tcu::TestCaseGroup> dimensionMultipleDiscontiguousDescriptorSetsGroup(
9883                                     new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name));
9884                                 void (*createTestsFunc)(
9885                                     tcu::TestCaseGroup *group, bool isPrimaryCmdBuf,
9886                                     DescriptorUpdateMethod updateMethod, vk::VkDescriptorType descriptorType,
9887                                     vk::VkShaderStageFlags existingStages, vk::VkShaderStageFlags activeStages,
9888                                     DescriptorSetCount descriptorSetCount, ShaderInputInterface dimension,
9889                                     uint32_t resourceFlags, const bool bind2);
9890 
9891                                 switch (s_descriptorTypes[descriptorNdx].descriptorType)
9892                                 {
9893                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
9894                                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
9895                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
9896                                     createTestsFunc = createShaderAccessImageTests;
9897                                     break;
9898 
9899                                 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
9900                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
9901                                     createTestsFunc = createShaderAccessTexelBufferTests;
9902                                     break;
9903 
9904                                 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
9905                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
9906                                 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
9907                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
9908                                     createTestsFunc = createShaderAccessBufferTests;
9909                                     break;
9910 
9911                                 default:
9912                                     createTestsFunc = nullptr;
9913                                     DE_FATAL("Impossible");
9914                                 }
9915 
9916                                 if (createTestsFunc)
9917                                 {
9918                                     createTestsFunc(
9919                                         dimensionSingleDescriptorSetGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9920                                         s_updateMethods[updateMethodNdx].method,
9921                                         s_descriptorTypes[descriptorNdx].descriptorType,
9922                                         s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9923                                         DESCRIPTOR_SET_COUNT_SINGLE, s_variableDimensions[dimensionNdx].dimension,
9924                                         s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9925 
9926                                     createTestsFunc(
9927                                         dimensionMultipleDescriptorSetsGroup.get(), s_bindTypes[bindTypeNdx].isPrimary,
9928                                         s_updateMethods[updateMethodNdx].method,
9929                                         s_descriptorTypes[descriptorNdx].descriptorType,
9930                                         s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9931                                         DESCRIPTOR_SET_COUNT_MULTIPLE, s_variableDimensions[dimensionNdx].dimension,
9932                                         s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9933 
9934                                     createTestsFunc(
9935                                         dimensionMultipleDiscontiguousDescriptorSetsGroup.get(),
9936                                         s_bindTypes[bindTypeNdx].isPrimary, s_updateMethods[updateMethodNdx].method,
9937                                         s_descriptorTypes[descriptorNdx].descriptorType,
9938                                         s_shaderStages[stageNdx].existingStages, s_shaderStages[stageNdx].activeStages,
9939                                         DESCRIPTOR_SET_COUNT_MULTIPLE_DISCONTIGUOUS,
9940                                         s_variableDimensions[dimensionNdx].dimension,
9941                                         s_descriptorTypes[descriptorNdx].flags, s_bindCommand[bindCommandNdx].bind2);
9942                                 }
9943                                 else
9944                                     DE_FATAL("Impossible");
9945 
9946                                 stageGroup->addChild(dimensionSingleDescriptorSetGroup.release());
9947 
9948                                 // Only one descriptor set layout can be created with VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR set
9949                                 if (s_updateMethods[updateMethodNdx].method == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH ||
9950                                     s_updateMethods[updateMethodNdx].method ==
9951                                         DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE)
9952                                     continue;
9953 
9954                                 multipleGroup->addChild(dimensionMultipleDescriptorSetsGroup.release());
9955                                 multipleDiscontiguousGroup->addChild(
9956                                     dimensionMultipleDiscontiguousDescriptorSetsGroup.release());
9957                             }
9958 
9959                             stageGroup->addChild(multipleGroup.release());
9960                             stageGroup->addChild(multipleDiscontiguousGroup.release());
9961                             typeGroup->addChild(stageGroup.release());
9962                         }
9963                     }
9964 
9965                     if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9966                     {
9967                         updateMethodGroup->addChild(typeGroup.release());
9968                     }
9969                     else
9970                     {
9971                         bindCommandGroup->addChild(typeGroup.release());
9972                     }
9973                 }
9974 
9975                 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL)
9976                 {
9977                     bindCommandGroup->addChild(updateMethodGroup.release());
9978                 }
9979             }
9980             bindGroup->addChild(bindCommandGroup.release());
9981         }
9982 
9983         group->addChild(bindGroup.release());
9984     }
9985 
9986     return group.release();
9987 }
9988 
9989 } // namespace BindingModel
9990 } // namespace vkt
9991