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