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