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