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