DO NOT MERGE Do not require signed zero support in ldexp tests() am: 5b076d99a8 ...
[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  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and/or associated documentation files (the
9  * "Materials"), to deal in the Materials without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Materials, and to
12  * permit persons to whom the Materials are furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be
16  * included in all copies or substantial portions of the Materials.
17  *
18  * The Materials are Confidential Information as defined by the
19  * Khronos Membership Agreement until designated non-confidential by
20  * Khronos, at which point this condition clause shall be removed.
21  *
22  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
29  *
30  *//*!
31  * \file
32  * \brief Binding shader access tests
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktBindingShaderAccessTests.hpp"
36
37 #include "vktTestCase.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkRef.hpp"
41 #include "vkRefUtil.hpp"
42 #include "vkPlatform.hpp"
43 #include "vkPrograms.hpp"
44 #include "vkMemUtil.hpp"
45 #include "vkBuilderUtil.hpp"
46 #include "vkQueryUtil.hpp"
47
48 #include "tcuVector.hpp"
49 #include "tcuVectorUtil.hpp"
50 #include "tcuTexture.hpp"
51 #include "tcuTextureUtil.hpp"
52 #include "tcuResultCollector.hpp"
53 #include "tcuTestLog.hpp"
54 #include "tcuRGBA.hpp"
55 #include "tcuSurface.hpp"
56 #include "tcuImageCompare.hpp"
57
58 #include "deUniquePtr.hpp"
59 #include "deSharedPtr.hpp"
60 #include "deStringUtil.hpp"
61 #include "deArrayUtil.hpp"
62
63 #include "qpInfo.h"
64
65 namespace vkt
66 {
67 namespace BindingModel
68 {
69 namespace
70 {
71
72 enum ResourceFlag
73 {
74         RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u),
75
76         RESOURCE_FLAG_LAST                              = (1u << 1u)
77 };
78
79 static const char* const s_quadrantGenVertexPosSource = "       highp int quadPhase = gl_VertexID % 6;\n"
80                                                                                                                 "       highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n"
81                                                                                                                 "       highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n"
82                                                                                                                 "       highp int quadOriginX = (gl_VertexID / 6) % 2;\n"
83                                                                                                                 "       highp int quadOriginY = (gl_VertexID / 6) / 2;\n"
84                                                                                                                 "       quadrant_id = gl_VertexID / 6;\n"
85                                                                                                                 "       result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n";
86
87 bool isUniformDescriptorType (vk::VkDescriptorType type)
88 {
89         return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
90                    type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
91                    type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
92 }
93
94 bool isDynamicDescriptorType (vk::VkDescriptorType type)
95 {
96         return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
97 }
98
99 vk::VkFormat mapToVkTextureFormat (const tcu::TextureFormat& format)
100 {
101         if (format == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
102                 return vk::VK_FORMAT_R8G8B8A8_UNORM;
103
104         DE_FATAL("Not implemented");
105         return vk::VK_FORMAT_UNDEFINED;
106 }
107
108 vk::VkImageType viewTypeToImageType (vk::VkImageViewType type)
109 {
110         switch (type)
111         {
112                 case vk::VK_IMAGE_VIEW_TYPE_1D:
113                 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:   return vk::VK_IMAGE_TYPE_1D;
114                 case vk::VK_IMAGE_VIEW_TYPE_2D:
115                 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:   return vk::VK_IMAGE_TYPE_2D;
116                 case vk::VK_IMAGE_VIEW_TYPE_3D:                 return vk::VK_IMAGE_TYPE_3D;
117                 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
118                 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return vk::VK_IMAGE_TYPE_2D;
119
120                 default:
121                         DE_FATAL("Impossible");
122                         return (vk::VkImageType)0;
123         }
124 }
125
126 vk::VkTexFilter mapMagFilterToVkTexFilter (tcu::Sampler::FilterMode mode)
127 {
128         switch (mode)
129         {
130                 case tcu::Sampler::NEAREST:     return vk::VK_TEX_FILTER_NEAREST;
131                 case tcu::Sampler::LINEAR:      return vk::VK_TEX_FILTER_LINEAR;
132
133                 default:
134                         DE_FATAL("Illegal filter mode");
135                         return (vk::VkTexFilter)0;
136         }
137 }
138
139 vk::VkTexFilter mapMinFilterToVkTexFilter (tcu::Sampler::FilterMode mode)
140 {
141         switch (mode)
142         {
143                 case tcu::Sampler::NEAREST:                                     return vk::VK_TEX_FILTER_NEAREST;
144                 case tcu::Sampler::LINEAR:                                      return vk::VK_TEX_FILTER_LINEAR;
145                 case tcu::Sampler::NEAREST_MIPMAP_NEAREST:      return vk::VK_TEX_FILTER_NEAREST;
146                 case tcu::Sampler::LINEAR_MIPMAP_NEAREST:       return vk::VK_TEX_FILTER_LINEAR;
147                 case tcu::Sampler::NEAREST_MIPMAP_LINEAR:       return vk::VK_TEX_FILTER_NEAREST;
148                 case tcu::Sampler::LINEAR_MIPMAP_LINEAR:        return vk::VK_TEX_FILTER_LINEAR;
149
150                 default:
151                         DE_FATAL("Illegal filter mode");
152                         return (vk::VkTexFilter)0;
153         }
154 }
155
156 vk::VkTexMipmapMode mapMinFilterToVkTexMipmapMode (tcu::Sampler::FilterMode mode)
157 {
158         switch (mode)
159         {
160                 case tcu::Sampler::NEAREST:                                     return vk::VK_TEX_MIPMAP_MODE_BASE;
161                 case tcu::Sampler::LINEAR:                                      return vk::VK_TEX_MIPMAP_MODE_BASE;
162                 case tcu::Sampler::NEAREST_MIPMAP_NEAREST:      return vk::VK_TEX_MIPMAP_MODE_NEAREST;
163                 case tcu::Sampler::LINEAR_MIPMAP_NEAREST:       return vk::VK_TEX_MIPMAP_MODE_NEAREST;
164                 case tcu::Sampler::NEAREST_MIPMAP_LINEAR:       return vk::VK_TEX_MIPMAP_MODE_LINEAR;
165                 case tcu::Sampler::LINEAR_MIPMAP_LINEAR:        return vk::VK_TEX_MIPMAP_MODE_LINEAR;
166
167                 default:
168                         DE_FATAL("Illegal filter mode");
169                         return (vk::VkTexMipmapMode)0;
170         }
171 }
172
173 vk::VkTexAddressMode mapToVkTexAddressMode (tcu::Sampler::WrapMode mode)
174 {
175         switch (mode)
176         {
177                 case tcu::Sampler::CLAMP_TO_EDGE:               return vk::VK_TEX_ADDRESS_MODE_CLAMP;
178                 case tcu::Sampler::CLAMP_TO_BORDER:             return vk::VK_TEX_ADDRESS_MODE_CLAMP_BORDER;
179                 case tcu::Sampler::REPEAT_GL:                   return vk::VK_TEX_ADDRESS_MODE_WRAP;
180                 case tcu::Sampler::MIRRORED_REPEAT_GL:  return vk::VK_TEX_ADDRESS_MODE_MIRROR;
181
182                 default:
183                         DE_FATAL("Illegal wrap mode");
184                         return (vk::VkTexAddressMode)0;
185         }
186 }
187
188 vk::VkCompareOp mapToVkCompareOp (tcu::Sampler::CompareMode mode)
189 {
190         switch (mode)
191         {
192                 case tcu::Sampler::COMPAREMODE_LESS:                            return vk::VK_COMPARE_OP_LESS;
193                 case tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL:           return vk::VK_COMPARE_OP_LESS_EQUAL;
194                 case tcu::Sampler::COMPAREMODE_GREATER:                         return vk::VK_COMPARE_OP_GREATER;
195                 case tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL:        return vk::VK_COMPARE_OP_GREATER_EQUAL;
196                 case tcu::Sampler::COMPAREMODE_EQUAL:                           return vk::VK_COMPARE_OP_EQUAL;
197                 case tcu::Sampler::COMPAREMODE_NOT_EQUAL:                       return vk::VK_COMPARE_OP_NOT_EQUAL;
198                 case tcu::Sampler::COMPAREMODE_ALWAYS:                          return vk::VK_COMPARE_OP_ALWAYS;
199                 case tcu::Sampler::COMPAREMODE_NEVER:                           return vk::VK_COMPARE_OP_NEVER;
200
201                 default:
202                         DE_FATAL("Illegal compare mode");
203                         return (vk::VkCompareOp)0;
204         }
205 }
206
207 deUint32 getTextureLevelPyramidDataSize (const tcu::TextureLevelPyramid& srcImage)
208 {
209         deUint32 dataSize = 0;
210         for (int level = 0; level < srcImage.getNumLevels(); ++level)
211         {
212                 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level);
213
214                 // tightly packed
215                 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
216
217                 dataSize += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
218         }
219         return dataSize;
220 }
221
222 void writeTextureLevelPyramidData (void* dst, deUint32 dstLen, const tcu::TextureLevelPyramid& srcImage, vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy>* copySlices)
223 {
224         // \note cube is copied face-by-face
225         const deUint32  arraySize       = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)                ? (srcImage.getLevel(0).getHeight()) :
226                                                                   (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)                ? (srcImage.getLevel(0).getDepth()) :
227                                                                   (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                                                                               ? (1) :
228                                                                   (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)    ? (srcImage.getLevel(0).getDepth()) :
229                                                                   ((deUint32)0);
230         deUint32                levelOffset     = 0;
231
232         DE_ASSERT(arraySize != 0);
233
234         for (int level = 0; level < srcImage.getNumLevels(); ++level)
235         {
236                 const tcu::ConstPixelBufferAccess       srcAccess               = srcImage.getLevel(level);
237                 const tcu::PixelBufferAccess            dstAccess               (srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), (deUint8*)dst + levelOffset);
238                 const deUint32                                          dataSize                = srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
239                 const deUint32                                          sliceDataSize   = dataSize / arraySize;
240                 const deInt32                                           sliceHeight             = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (srcAccess.getHeight());
241                 const deInt32                                           sliceDepth              = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1);
242                 const tcu::IVec3                                        sliceSize               (srcAccess.getWidth(), sliceHeight, sliceDepth);
243
244                 // tightly packed
245                 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch());
246
247                 for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx)
248                 {
249                         const vk::VkBufferImageCopy copySlice =
250                         {
251                                 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize,       // bufferOffset
252                                 (deUint32)sliceSize.x(),                                                                        // bufferRowLength
253                                 (deUint32)sliceSize.y(),                                                                        // bufferImageHeight
254                                 {
255                                         vk::VK_IMAGE_ASPECT_COLOR,                      // aspect
256                                         (deUint32)level,                                        // mipLevel
257                                         (deUint32)sliceNdx,                                     // arrayLayer
258                                         1u,                                                                     // arraySize
259                                 },                                                                                                                      // imageSubresource
260                                 {
261                                         0,
262                                         0,
263                                         0,
264                                 },                                                                                                                      // imageOffset
265                                 {
266                                         sliceSize.x(),
267                                         sliceSize.y(),
268                                         sliceSize.z(),
269                                 }                                                                                                                       // imageExtent
270                         };
271                         copySlices->push_back(copySlice);
272                 }
273
274                 DE_ASSERT(arraySize * sliceDataSize == dataSize);
275
276                 tcu::copy(dstAccess, srcAccess);
277                 levelOffset += dataSize;
278         }
279
280         DE_ASSERT(dstLen == levelOffset);
281         DE_UNREF(dstLen);
282 }
283
284 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkBuffer buffer, vk::MemoryRequirement requirement)
285 {
286         const vk::VkMemoryRequirements  requirements    = vk::getBufferMemoryRequirements(vki, device, buffer);
287         de::MovePtr<vk::Allocation>             allocation              = allocator.allocate(requirements, requirement);
288
289         VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
290         return allocation;
291 }
292
293 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkImage image, vk::MemoryRequirement requirement)
294 {
295         const vk::VkMemoryRequirements  requirements    = vk::getImageMemoryRequirements(vki, device, image);
296         de::MovePtr<vk::Allocation>             allocation              = allocator.allocate(requirements, requirement);
297
298         VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
299         return allocation;
300 }
301
302 vk::VkDescriptorInfo createDescriptorInfo (vk::VkBuffer buffer, vk::VkDeviceSize offset, vk::VkDeviceSize range)
303 {
304         const vk::VkDescriptorInfo resultInfo =
305         {
306                 0,                                                      // bufferView
307                 0,                                                      // sampler
308                 0,                                                      // imageView
309                 (vk::VkImageLayout)0,           // imageLayout
310                 { buffer, offset, range }       // bufferInfo
311         };
312         return resultInfo;
313 }
314
315 vk::VkDescriptorInfo createDescriptorInfo (vk::VkBufferView bufferView)
316 {
317         const vk::VkDescriptorInfo resultInfo =
318         {
319                 bufferView,                                     // bufferView
320                 0,                                                      // sampler
321                 0,                                                      // imageView
322                 (vk::VkImageLayout)0,           // imageLayout
323                 { (vk::VkBuffer)0, 0, 0 }       // bufferInfo
324         };
325         return resultInfo;
326 }
327
328 vk::VkDescriptorInfo createDescriptorInfo (vk::VkSampler sampler)
329 {
330         const vk::VkDescriptorInfo resultInfo =
331         {
332                 0,                                                      // bufferView
333                 sampler,                                        // sampler
334                 0,                                                      // imageView
335                 (vk::VkImageLayout)0,           // imageLayout
336                 { (vk::VkBuffer)0, 0, 0 }       // bufferInfo
337         };
338         return resultInfo;
339 }
340
341 vk::VkDescriptorInfo createDescriptorInfo (vk::VkImageView imageView, vk::VkImageLayout layout)
342 {
343         const vk::VkDescriptorInfo resultInfo =
344         {
345                 0,                                                      // bufferView
346                 0,                                                      // sampler
347                 imageView,                                      // imageView
348                 layout,                                         // imageLayout
349                 { (vk::VkBuffer)0, 0, 0 }       // bufferInfo
350         };
351         return resultInfo;
352 }
353
354 vk::VkDescriptorInfo createDescriptorInfo (vk::VkSampler sampler, vk::VkImageView imageView, vk::VkImageLayout layout)
355 {
356         const vk::VkDescriptorInfo resultInfo =
357         {
358                 0,                                                      // bufferView
359                 sampler,                                        // sampler
360                 imageView,                                      // imageView
361                 layout,                                         // imageLayout
362                 { (vk::VkBuffer)0, 0, 0 }       // bufferInfo
363         };
364         return resultInfo;
365 }
366
367 vk::VkClearValue createClearValueColor (const tcu::Vec4& color)
368 {
369         vk::VkClearValue retVal;
370
371         retVal.color.float32[0] = color.x();
372         retVal.color.float32[1] = color.y();
373         retVal.color.float32[2] = color.z();
374         retVal.color.float32[3] = color.w();
375
376         return retVal;
377 };
378
379 void drawQuadrantReferenceResult (const tcu::PixelBufferAccess& dst, const tcu::Vec4& c1, const tcu::Vec4& c2, const tcu::Vec4& c3, const tcu::Vec4& c4)
380 {
381         tcu::clear(tcu::getSubregion(dst, 0,                                    0,                                              dst.getWidth() / 2,                                             dst.getHeight() / 2),                                   c1);
382         tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2,   0,                                              dst.getWidth() - dst.getWidth() / 2,    dst.getHeight() / 2),                                   c2);
383         tcu::clear(tcu::getSubregion(dst, 0,                                    dst.getHeight() / 2,    dst.getWidth() / 2,                                             dst.getHeight() - dst.getHeight() / 2), c3);
384         tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2,   dst.getHeight() / 2,    dst.getWidth() - dst.getWidth() / 2,    dst.getHeight() - dst.getHeight() / 2), c4);
385 }
386
387 class SingleTargetRenderInstance : public vkt::TestInstance
388 {
389 public:
390                                                                                         SingleTargetRenderInstance      (Context&                       context,
391                                                                                                                                                  const tcu::UVec2&      size);
392
393 private:
394         static vk::Move<vk::VkImage>                    createColorAttachment           (const vk::DeviceInterface&             vki,
395                                                                                                                                                  vk::VkDevice                                   device,
396                                                                                                                                                  vk::Allocator&                                 allocator,
397                                                                                                                                                  const tcu::TextureFormat&              format,
398                                                                                                                                                  const tcu::UVec2&                              size,
399                                                                                                                                                  de::MovePtr<vk::Allocation>*   outAllocation);
400
401         static vk::Move<vk::VkImageView>                createColorAttachmentView       (const vk::DeviceInterface&     vki,
402                                                                                                                                                  vk::VkDevice                           device,
403                                                                                                                                                  const tcu::TextureFormat&      format,
404                                                                                                                                                  vk::VkImage                            image);
405
406         static vk::Move<vk::VkRenderPass>               createRenderPass                        (const vk::DeviceInterface&     vki,
407                                                                                                                                                  vk::VkDevice                           device,
408                                                                                                                                                  const tcu::TextureFormat&      format);
409
410         static vk::Move<vk::VkFramebuffer>              createFramebuffer                       (const vk::DeviceInterface&     vki,
411                                                                                                                                                  vk::VkDevice                           device,
412                                                                                                                                                  vk::VkRenderPass                       renderpass,
413                                                                                                                                                  vk::VkImageView                        colorAttachmentView,
414                                                                                                                                                  const tcu::UVec2&                      size);
415
416         static vk::Move<vk::VkCmdPool>                  createCommandPool                       (const vk::DeviceInterface&     vki,
417                                                                                                                                                  vk::VkDevice                           device,
418                                                                                                                                                  deUint32                                       queueFamilyIndex);
419
420         virtual void                                                    logTestPlan                                     (void) const = 0;
421         virtual void                                                    renderToTarget                          (void) = 0;
422         virtual tcu::TestStatus                                 verifyResultImage                       (const tcu::ConstPixelBufferAccess& result) const = 0;
423
424         void                                                                    readRenderTarget                        (tcu::TextureLevel& dst);
425         tcu::TestStatus                                                 iterate                                         (void);
426
427 protected:
428         const tcu::TextureFormat                                m_targetFormat;
429         const tcu::UVec2                                                m_targetSize;
430
431         const vk::DeviceInterface&                              m_vki;
432         const vk::VkDevice                                              m_device;
433         const vk::VkQueue                                               m_queue;
434         const deUint32                                                  m_queueFamilyIndex;
435         vk::Allocator&                                                  m_allocator;
436         de::MovePtr<vk::Allocation>                             m_colorAttachmentMemory;
437         const vk::Unique<vk::VkImage>                   m_colorAttachmentImage;
438         const vk::Unique<vk::VkImageView>               m_colorAttachmentView;
439         const vk::Unique<vk::VkRenderPass>              m_renderPass;
440         const vk::Unique<vk::VkFramebuffer>             m_framebuffer;
441         const vk::Unique<vk::VkCmdPool>                 m_cmdPool;
442
443         bool                                                                    m_firstIteration;
444 };
445
446 SingleTargetRenderInstance::SingleTargetRenderInstance (Context&                        context,
447                                                                                                                 const tcu::UVec2&       size)
448         : vkt::TestInstance                     (context)
449         , m_targetFormat                        (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
450         , m_targetSize                          (size)
451         , m_vki                                         (context.getDeviceInterface())
452         , m_device                                      (context.getDevice())
453         , m_queue                                       (context.getUniversalQueue())
454         , m_queueFamilyIndex            (context.getUniversalQueueFamilyIndex())
455         , m_allocator                           (context.getDefaultAllocator())
456         , m_colorAttachmentMemory       (DE_NULL)
457         , m_colorAttachmentImage        (createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory))
458         , m_colorAttachmentView         (createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage))
459         , m_renderPass                          (createRenderPass(m_vki, m_device, m_targetFormat))
460         , m_framebuffer                         (createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize))
461         , m_cmdPool                                     (createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex()))
462         , m_firstIteration                      (true)
463 {
464 }
465
466 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment (const vk::DeviceInterface&             vki,
467                                                                                                                                                  vk::VkDevice                                   device,
468                                                                                                                                                  vk::Allocator&                                 allocator,
469                                                                                                                                                  const tcu::TextureFormat&              format,
470                                                                                                                                                  const tcu::UVec2&                              size,
471                                                                                                                                                  de::MovePtr<vk::Allocation>*   outAllocation)
472 {
473         const vk::VkImageCreateInfo     imageInfo       =
474         {
475                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
476                 DE_NULL,
477                 vk::VK_IMAGE_TYPE_2D,                                                   // imageType
478                 mapToVkTextureFormat(format),                                   // format
479                 { (deInt32)size.x(), (deInt32)size.y(), 1 },    // extent
480                 1,                                                                                              // mipLevels
481                 1,                                                                                              // arraySize
482                 1,                                                                                              // samples
483                 vk::VK_IMAGE_TILING_OPTIMAL,                                    // tiling
484                 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT,       // usage
485                 0,                                                                                              // flags
486                 vk::VK_SHARING_MODE_EXCLUSIVE,                                  // sharingMode
487                 0u,                                                                                             // queueFamilyCount
488                 DE_NULL,                                                                                // pQueueFamilyIndices
489                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // initialLayout
490         };
491
492         vk::Move<vk::VkImage>           image           (vk::createImage(vki, device, &imageInfo));
493         de::MovePtr<vk::Allocation>     allocation      (allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any));
494
495         *outAllocation = allocation;
496         return image;
497 }
498
499 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView (const vk::DeviceInterface&     vki,
500                                                                                                                                                                  vk::VkDevice                           device,
501                                                                                                                                                                  const tcu::TextureFormat&      format,
502                                                                                                                                                                  vk::VkImage                            image)
503 {
504         const vk::VkImageViewCreateInfo createInfo =
505         {
506                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
507                 DE_NULL,
508                 image,                                                  // image
509                 vk::VK_IMAGE_VIEW_TYPE_2D,              // viewType
510                 mapToVkTextureFormat(format),   // format
511                 { vk::VK_CHANNEL_SWIZZLE_R, vk::VK_CHANNEL_SWIZZLE_G, vk::VK_CHANNEL_SWIZZLE_B, vk::VK_CHANNEL_SWIZZLE_A },
512                 {
513                         vk::VK_IMAGE_ASPECT_COLOR_BIT,  // aspectMask
514                         0u,                                                             // baseMipLevel
515                         1u,                                                             // mipLevels
516                         0u,                                                             // baseArrayLayer
517                         1u,                                                             // arraySize
518                 },
519                 0u,                                                             // flags
520         };
521
522         return vk::createImageView(vki, device, &createInfo);
523 }
524
525 vk::Move<vk::VkRenderPass> SingleTargetRenderInstance::createRenderPass (const vk::DeviceInterface&             vki,
526                                                                                                                                                  vk::VkDevice                                   device,
527                                                                                                                                                  const tcu::TextureFormat&              format)
528 {
529         const vk::VkAttachmentDescription       attachmentDescription   =
530         {
531                 vk::VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,
532                 DE_NULL,
533                 mapToVkTextureFormat(format),                                   // format
534                 1u,                                                                                             // samples
535                 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                                // loadOp
536                 vk::VK_ATTACHMENT_STORE_OP_STORE,                               // storeOp
537                 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                    // stencilLoadOp
538                 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // stencilStoreOp
539                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // initialLayout
540                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // finalLayout
541                 0u,                                                                                             // flags
542         };
543         const vk::VkAttachmentReference         colorAttachment                 =
544         {
545                 0u,                                                                                             // attachment
546                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL    // layout
547         };
548         const vk::VkAttachmentReference         depthStencilAttachment  =
549         {
550                 vk::VK_NO_ATTACHMENT,                                                   // attachment
551                 vk::VK_IMAGE_LAYOUT_UNDEFINED                                   // layout
552         };
553         const vk::VkSubpassDescription          subpass                                 =
554         {
555                 vk::VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,
556                 DE_NULL,
557                 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                    // pipelineBindPoint
558                 0u,                                                                                             // flags
559                 0u,                                                                                             // inputCount
560                 DE_NULL,                                                                                // inputAttachments
561                 1u,                                                                                             // colorCount
562                 &colorAttachment,                                                               // pColorAttachments
563                 DE_NULL,                                                                                // pResolveAttachments
564                 depthStencilAttachment,                                                 // depthStencilAttachment
565                 0u,                                                                                             // preserveCount
566                 DE_NULL                                                                                 // pPreserveAttachments
567         };
568         const vk::VkRenderPassCreateInfo        renderPassCreateInfo    =
569         {
570                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
571                 DE_NULL,
572                 1u,                                                                                             // attachmentCount
573                 &attachmentDescription,                                                 // pAttachments
574                 1u,                                                                                             // subpassCount
575                 &subpass,                                                                               // pSubpasses
576                 0u,                                                                                             // dependencyCount
577                 DE_NULL,                                                                                // pDependencies
578         };
579
580         return vk::createRenderPass(vki, device, &renderPassCreateInfo);
581 }
582
583 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer (const vk::DeviceInterface&   vki,
584                                                                                                                                                    vk::VkDevice                                 device,
585                                                                                                                                                    vk::VkRenderPass                             renderpass,
586                                                                                                                                                    vk::VkImageView                              colorAttachmentView,
587                                                                                                                                                    const tcu::UVec2&                    size)
588 {
589         const vk::VkFramebufferCreateInfo       framebufferCreateInfo   =
590         {
591                 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
592                 DE_NULL,
593                 renderpass,                             // renderPass
594                 1u,                                             // attachmentCount
595                 &colorAttachmentView,   // pAttachments
596                 size.x(),                               // width
597                 size.y(),                               // height
598                 1,                                              // layers
599         };
600
601         return vk::createFramebuffer(vki, device, &framebufferCreateInfo);
602 }
603
604 vk::Move<vk::VkCmdPool> SingleTargetRenderInstance::createCommandPool (const vk::DeviceInterface&       vki,
605                                                                                                                                            vk::VkDevice                                 device,
606                                                                                                                                            deUint32                                             queueFamilyIndex)
607 {
608         const vk::VkCmdPoolCreateInfo createInfo =
609         {
610                 vk::VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,
611                 DE_NULL,
612                 queueFamilyIndex,                                               // queueFamilyIndex
613                 vk::VK_CMD_POOL_CREATE_TRANSIENT_BIT,   // flags
614         };
615         return vk::createCommandPool(vki, device, &createInfo);
616 }
617
618 void SingleTargetRenderInstance::readRenderTarget (tcu::TextureLevel& dst)
619 {
620         const deUint64                                          pixelDataSize                           = (deUint64)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize());
621         const vk::VkBufferCreateInfo            bufferCreateInfo                        =
622         {
623                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
624                 DE_NULL,
625                 pixelDataSize,                                                                  // size
626                 vk::VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT,   // usage
627                 0u,                                                                                             // flags
628                 vk::VK_SHARING_MODE_EXCLUSIVE,                                  // sharingMode
629                 0u,                                                                                             // queueFamilyCount
630                 DE_NULL,                                                                                // pQueueFamilyIndices
631         };
632         const vk::Unique<vk::VkBuffer>          buffer                                          (vk::createBuffer(m_vki, m_device, &bufferCreateInfo));
633         const vk::VkImageSubresourceRange       fullSubrange                            =
634         {
635                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
636                 0u,                                                                                             // baseMipLevel
637                 1u,                                                                                             // mipLevels
638                 0u,                                                                                             // baseArraySlice
639                 1u,                                                                                             // arraySize
640         };
641         const vk::VkImageMemoryBarrier          imageBarrier                            =
642         {
643                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
644                 DE_NULL,
645                 vk::VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT,              // outputMask
646                 vk::VK_MEMORY_INPUT_TRANSFER_BIT,                               // inputMask
647                 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // oldLayout
648                 vk::VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL,    // newLayout
649                 vk::VK_QUEUE_FAMILY_IGNORED,                                    // srcQueueFamilyIndex
650                 vk::VK_QUEUE_FAMILY_IGNORED,                                    // destQueueFamilyIndex
651                 *m_colorAttachmentImage,                                                // image
652                 fullSubrange,                                                                   // subresourceRange
653         };
654         const vk::VkBufferMemoryBarrier         memoryBarrier                           =
655         {
656                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
657                 DE_NULL,
658                 vk::VK_MEMORY_OUTPUT_TRANSFER_BIT,                              // outputMask
659                 vk::VK_MEMORY_INPUT_HOST_READ_BIT,                              // inputMask
660                 vk::VK_QUEUE_FAMILY_IGNORED,                                    // srcQueueFamilyIndex
661                 vk::VK_QUEUE_FAMILY_IGNORED,                                    // destQueueFamilyIndex
662                 *buffer,                                                                                // buffer
663                 0u,                                                                                             // offset
664                 (vk::VkDeviceSize)pixelDataSize                                 // size
665         };
666         const vk::VkCmdBufferCreateInfo         cmdBufCreateInfo                        =
667         {
668                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
669                 DE_NULL,
670                 *m_cmdPool,                                                     // cmdPool
671                 vk::VK_CMD_BUFFER_LEVEL_PRIMARY,        // level
672                 0u,                                                                     // flags
673         };
674         const vk::VkFenceCreateInfo                     fenceCreateInfo                         =
675         {
676                 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
677                 DE_NULL,
678                 0u,                                                                                             // flags
679         };
680         const vk::VkCmdBufferBeginInfo          cmdBufBeginInfo                         =
681         {
682                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
683                 DE_NULL,
684                 vk::VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | vk::VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,    // flags
685                 (vk::VkRenderPass)0u,                                                                                                                                                   // renderPass
686                 0u,                                                                                                                                                                                             // subpass
687                 (vk::VkFramebuffer)0u,                                                                                                                                                  // framebuffer
688         };
689         const vk::VkImageSubresourceCopy        firstSlice                                      =
690         {
691                 vk::VK_IMAGE_ASPECT_COLOR,                                              // aspect
692                 0,                                                                                              // mipLevel
693                 0,                                                                                              // arrayLayer
694                 1,                                                                                              // arraySize
695         };
696         const vk::VkBufferImageCopy                     copyRegion                                      =
697         {
698                 0u,                                                                                             // bufferOffset
699                 m_targetSize.x(),                                                               // bufferRowLength
700                 m_targetSize.y(),                                                               // bufferImageHeight
701                 firstSlice,                                                                             // imageSubresource
702                 { 0, 0, 0 },                                                                    // imageOffset
703                 { (deInt32)m_targetSize.x(), (deInt32)m_targetSize.y(), 1 }             // imageExtent
704         };
705
706         const de::MovePtr<vk::Allocation>       bufferMemory                            = allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible);
707
708         const vk::Unique<vk::VkCmdBuffer>       cmd                                                     (vk::createCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
709         const vk::Unique<vk::VkFence>           cmdCompleteFence                        (vk::createFence(m_vki, m_device, &fenceCreateInfo));
710         const void* const                                       imageBarrierPtr                         = &imageBarrier;
711         const void* const                                       bufferBarrierPtr                        = &memoryBarrier;
712         const deUint64                                          infiniteTimeout                         = ~(deUint64)0u;
713
714         // copy content to buffer
715         VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
716         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_FALSE, 1, &imageBarrierPtr);
717         m_vki.cmdCopyImageToBuffer(*cmd, *m_colorAttachmentImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, *buffer, 1, &copyRegion);
718         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, 1, &bufferBarrierPtr);
719         VK_CHECK(m_vki.endCommandBuffer(*cmd));
720
721         // wait for transfer to complete
722         VK_CHECK(m_vki.queueSubmit(m_queue, 1, &cmd.get(), *cmdCompleteFence));
723         VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
724
725         dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y());
726
727         // copy data
728         invalidateMappedMemoryRange(m_vki, m_device, bufferMemory->getMemory(), bufferMemory->getOffset(), pixelDataSize);
729         tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr()));
730 }
731
732 tcu::TestStatus SingleTargetRenderInstance::iterate (void)
733 {
734         tcu::TextureLevel resultImage;
735
736         // log
737         if (m_firstIteration)
738         {
739                 logTestPlan();
740                 m_firstIteration = false;
741         }
742
743         // render
744         {
745                 // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
746                 const vk::VkImageSubresourceRange       fullSubrange                            =
747                 {
748                         vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
749                         0u,                                                                                             // baseMipLevel
750                         1u,                                                                                             // mipLevels
751                         0u,                                                                                             // baseArraySlice
752                         1u,                                                                                             // arraySize
753                 };
754                 const vk::VkImageMemoryBarrier          imageBarrier                            =
755                 {
756                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
757                         DE_NULL,
758                         0u,                                                                                             // outputMask
759                         vk::VK_MEMORY_INPUT_COLOR_ATTACHMENT_BIT,               // inputMask
760                         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // oldLayout
761                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // newLayout
762                         vk::VK_QUEUE_FAMILY_IGNORED,                                    // srcQueueFamilyIndex
763                         vk::VK_QUEUE_FAMILY_IGNORED,                                    // destQueueFamilyIndex
764                         *m_colorAttachmentImage,                                                // image
765                         fullSubrange,                                                                   // subresourceRange
766                 };
767                 const vk::VkCmdBufferCreateInfo         cmdBufCreateInfo                        =
768                 {
769                         vk::VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
770                         DE_NULL,
771                         *m_cmdPool,                                                                             // cmdPool
772                         vk::VK_CMD_BUFFER_LEVEL_PRIMARY,                                // level
773                         0u,                                                                                             // flags
774                 };
775                 const vk::VkCmdBufferBeginInfo          cmdBufBeginInfo                         =
776                 {
777                         vk::VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
778                         DE_NULL,
779                         vk::VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | vk::VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,    // flags
780                         (vk::VkRenderPass)0u,                                                                                                                                                   // renderPass
781                         0u,                                                                                                                                                                                             // subpass
782                         (vk::VkFramebuffer)0u,                                                                                                                                                  // framebuffer
783                 };
784
785                 const vk::Unique<vk::VkCmdBuffer>       cmd                                     (vk::createCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
786                 const void* const                                       imageBarrierPtr         = &imageBarrier;
787
788                 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
789                 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, 1, &imageBarrierPtr);
790                 VK_CHECK(m_vki.endCommandBuffer(*cmd));
791                 VK_CHECK(m_vki.queueSubmit(m_queue, 1, &cmd.get(), 0));
792
793                 // and then render to
794                 renderToTarget();
795         }
796
797         // read and verify
798         readRenderTarget(resultImage);
799         return verifyResultImage(resultImage.getAccess());
800 }
801
802 class RenderInstanceShaders
803 {
804 public:
805                                                                                                                 RenderInstanceShaders           (const vk::DeviceInterface&             vki,
806                                                                                                                                                                          vk::VkDevice                                   device,
807                                                                                                                                                                          const vk::BinaryCollection&    programCollection);
808
809         inline bool                                                                                     hasTessellationStage            (void) const { return *m_tessCtrlShader != 0 || *m_tessEvalShader != 0; }
810         inline deUint32                                                                         getNumStages                            (void) const { return (deUint32)m_stageInfos.size();                                    }
811         inline const vk::VkPipelineShaderStageCreateInfo*       getStages                                       (void) const { return &m_stageInfos[0];                                                                 }
812
813 private:
814         void                                                                                            addStage                                        (const vk::DeviceInterface&             vki,
815                                                                                                                                                                          vk::VkDevice                                   device,
816                                                                                                                                                                          const vk::BinaryCollection&    programCollection,
817                                                                                                                                                                          const char*                                    name,
818                                                                                                                                                                          vk::VkShaderStage                              stage,
819                                                                                                                                                                          vk::Move<vk::VkShaderModule>*  outModule,
820                                                                                                                                                                          vk::Move<vk::VkShader>*                outShader);
821
822         vk::VkPipelineShaderStageCreateInfo                                     getShaderStageCreateInfo        (vk::VkShaderStage stage, vk::VkShader shader) const;
823
824         vk::Move<vk::VkShaderModule>                                            m_vertexShaderModule;
825         vk::Move<vk::VkShader>                                                          m_vertexShader;
826         vk::Move<vk::VkShaderModule>                                            m_tessCtrlShaderModule;
827         vk::Move<vk::VkShader>                                                          m_tessCtrlShader;
828         vk::Move<vk::VkShaderModule>                                            m_tessEvalShaderModule;
829         vk::Move<vk::VkShader>                                                          m_tessEvalShader;
830         vk::Move<vk::VkShaderModule>                                            m_geometryShaderModule;
831         vk::Move<vk::VkShader>                                                          m_geometryShader;
832         vk::Move<vk::VkShaderModule>                                            m_fragmentShaderModule;
833         vk::Move<vk::VkShader>                                                          m_fragmentShader;
834         std::vector<vk::VkPipelineShaderStageCreateInfo>        m_stageInfos;
835 };
836
837 RenderInstanceShaders::RenderInstanceShaders (const vk::DeviceInterface&        vki,
838                                                                                           vk::VkDevice                                  device,
839                                                                                           const vk::BinaryCollection&   programCollection)
840 {
841         addStage(vki, device, programCollection, "vertex",              vk::VK_SHADER_STAGE_VERTEX,                             &m_vertexShaderModule,          &m_vertexShader);
842         addStage(vki, device, programCollection, "tess_ctrl",   vk::VK_SHADER_STAGE_TESS_CONTROL,               &m_tessCtrlShaderModule,        &m_tessCtrlShader);
843         addStage(vki, device, programCollection, "tess_eval",   vk::VK_SHADER_STAGE_TESS_EVALUATION,    &m_tessEvalShaderModule,        &m_tessEvalShader);
844         addStage(vki, device, programCollection, "geometry",    vk::VK_SHADER_STAGE_GEOMETRY,                   &m_geometryShaderModule,        &m_geometryShader);
845         addStage(vki, device, programCollection, "fragment",    vk::VK_SHADER_STAGE_FRAGMENT,                   &m_fragmentShaderModule,        &m_fragmentShader);
846
847         DE_ASSERT(!m_stageInfos.empty());
848 }
849
850 void RenderInstanceShaders::addStage (const vk::DeviceInterface&                vki,
851                                                                           vk::VkDevice                                          device,
852                                                                           const vk::BinaryCollection&           programCollection,
853                                                                           const char*                                           name,
854                                                                           vk::VkShaderStage                                     stage,
855                                                                           vk::Move<vk::VkShaderModule>*         outModule,
856                                                                           vk::Move<vk::VkShader>*                       outShader)
857 {
858         if (programCollection.contains(name))
859         {
860                 vk::Move<vk::VkShaderModule>    module          = createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0);
861                 const vk::VkShaderCreateInfo    createInfo      =
862                 {
863                         vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
864                         DE_NULL,
865                         *module,                // module
866                         "main",                 // pName
867                         0u,                             // flags
868                         stage
869                 };
870                 vk::Move<vk::VkShader>                  shader          = vk::createShader(vki, device, &createInfo);
871
872                 m_stageInfos.push_back(getShaderStageCreateInfo(stage, *shader));
873                 *outModule = module;
874                 *outShader = shader;
875         }
876 }
877
878 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo (vk::VkShaderStage stage, vk::VkShader shader) const
879 {
880         const vk::VkPipelineShaderStageCreateInfo       stageCreateInfo =
881         {
882                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
883                 DE_NULL,
884                 stage,                  // stage
885                 shader,                 // shader
886                 DE_NULL,                // pSpecializationInfo
887         };
888         return stageCreateInfo;
889 }
890
891 class SingleCmdRenderInstance : public SingleTargetRenderInstance
892 {
893 public:
894                                                                         SingleCmdRenderInstance (Context&                       context,
895                                                                                                                          bool                           isPrimaryCmdBuf,
896                                                                                                                          const tcu::UVec2&      renderSize);
897
898 private:
899         vk::Move<vk::VkPipeline>                createPipeline                          (vk::VkPipelineLayout pipelineLayout);
900
901         virtual vk::VkPipelineLayout    getPipelineLayout                       (void) const = 0;
902         virtual void                                    writeDrawCmdBuffer                      (vk::VkCmdBuffer cmd) const = 0;
903
904         void                                                    renderToTarget                          (void);
905
906         const bool                                              m_isPrimaryCmdBuf;
907 };
908
909 SingleCmdRenderInstance::SingleCmdRenderInstance (Context&                      context,
910                                                                                                   bool                          isPrimaryCmdBuf,
911                                                                                                   const tcu::UVec2&     renderSize)
912         : SingleTargetRenderInstance    (context, renderSize)
913         , m_isPrimaryCmdBuf                             (isPrimaryCmdBuf)
914 {
915 }
916
917 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline (vk::VkPipelineLayout pipelineLayout)
918 {
919         const RenderInstanceShaders                                                     shaderStages            (m_vki, m_device, m_context.getBinaryCollection());
920         const vk::VkPrimitiveTopology                                           topology                        = shaderStages.hasTessellationStage() ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
921         const vk::VkPipelineVertexInputStateCreateInfo          vertexInputState        =
922         {
923                 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
924                 DE_NULL,
925                 0u,                                                                                     // bindingCount
926                 DE_NULL,                                                                        // pVertexBindingDescriptions
927                 0u,                                                                                     // attributeCount
928                 DE_NULL,                                                                        // pVertexAttributeDescriptions
929         };
930         const vk::VkPipelineInputAssemblyStateCreateInfo        iaState                         =
931         {
932                 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
933                 DE_NULL,
934                 topology,                                                                       // topology
935                 vk::VK_FALSE,                                                           // primitiveRestartEnable
936         };
937         const vk::VkPipelineTessellationStateCreateInfo         tessState                       =
938         {
939                 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
940                 DE_NULL,
941                 3u,                                                                                     // patchControlPoints
942         };
943         const vk::VkViewport                                                            viewport                        =
944         {
945                 0.0f,                                                                           // originX
946                 0.0f,                                                                           // originY
947                 float(m_targetSize.x()),                                        // width
948                 float(m_targetSize.y()),                                        // height
949                 0.0f,                                                                           // minDepth
950                 1.0f,                                                                           // maxDepth
951         };
952         const vk::VkRect2D                                                                      renderArea                      =
953         {
954                 { 0, 0 },                                                                                                       // offset
955                 { (deInt32)m_targetSize.x(), (deInt32)m_targetSize.y() },       // extent
956         };
957         const vk::VkPipelineViewportStateCreateInfo                     vpState                         =
958         {
959                 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
960                 DE_NULL,
961                 1u,                                                                                     // viewportCount
962                 &viewport,
963                 1u,
964                 &renderArea,
965         };
966         const vk::VkPipelineRasterStateCreateInfo                       rsState                         =
967         {
968                 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,
969                 DE_NULL,
970                 vk::VK_TRUE,                                                            // depthClipEnable
971                 vk::VK_FALSE,                                                           // rasterizerDiscardEnable
972                 vk::VK_FILL_MODE_SOLID,                                         // fillMode
973                 vk::VK_CULL_MODE_NONE,                                          // cullMode
974                 vk::VK_FRONT_FACE_CCW,                                          // frontFace
975                 vk::VK_FALSE,                                                           // depthBiasEnable
976                 0.0f,                                                                           // depthBias
977                 0.0f,                                                                           // depthBiasClamp
978                 0.0f,                                                                           // slopeScaledDepthBias
979                 1.0f,                                                                           // lineWidth
980         };
981         const vk::VkSampleMask                                                          sampleMask                      = 0x01u;
982         const vk::VkPipelineMultisampleStateCreateInfo          msState                         =
983         {
984                 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
985                 DE_NULL,
986                 1u,                                                                                     // rasterSamples
987                 vk::VK_FALSE,                                                           // sampleShadingEnable
988                 0.0f,                                                                           // minSampleShading
989                 &sampleMask                                                                     // sampleMask
990         };
991         const vk::VkPipelineDepthStencilStateCreateInfo         dsState                         =
992         {
993                 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
994                 DE_NULL,
995                 vk::VK_FALSE,                                                           // depthTestEnable
996                 vk::VK_FALSE,                                                           // depthWriteEnable
997                 vk::VK_COMPARE_OP_ALWAYS,                                       // depthCompareOp
998                 vk::VK_FALSE,                                                           // depthBoundsTestEnable
999                 vk::VK_FALSE,                                                           // stencilTestEnable
1000                 { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },       // front
1001                 { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },       // back
1002                 -1.0f,                                                                          // minDepthBounds
1003                 +1.0f,                                                                          // maxDepthBounds
1004         };
1005         const vk::VkPipelineColorBlendAttachmentState           cbAttachment            =
1006         {
1007                 vk::VK_FALSE,                                                           // blendEnable
1008                 vk::VK_BLEND_ZERO,                                                      // srcBlendColor
1009                 vk::VK_BLEND_ZERO,                                                      // destBlendColor
1010                 vk::VK_BLEND_OP_ADD,                                            // blendOpColor
1011                 vk::VK_BLEND_ZERO,                                                      // srcBlendAlpha
1012                 vk::VK_BLEND_ZERO,                                                      // destBlendAlpha
1013                 vk::VK_BLEND_OP_ADD,                                            // blendOpAlpha
1014                 vk::VK_CHANNEL_R_BIT | vk::VK_CHANNEL_G_BIT | vk::VK_CHANNEL_B_BIT | vk::VK_CHANNEL_A_BIT,      // channelWriteMask
1015         };
1016         const vk::VkPipelineColorBlendStateCreateInfo           cbState                         =
1017         {
1018                 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1019                 DE_NULL,
1020                 vk::VK_FALSE,                                                           // alphaToCoverageEnable
1021                 vk::VK_FALSE,                                                           // alphaToOneEnable
1022                 vk::VK_FALSE,                                                           // logicOpEnable
1023                 vk::VK_LOGIC_OP_CLEAR,                                          // logicOp
1024                 1u,                                                                                     // attachmentCount
1025                 &cbAttachment,                                                          // pAttachments
1026                 { 0.0f, 0.0f, 0.0f, 0.0f },                                     // blendConst
1027         };
1028         const vk::VkPipelineDynamicStateCreateInfo                      dynState                        =
1029         {
1030                 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
1031                 DE_NULL,
1032                 0u,                                                                                     // dynamicStateCount
1033                 DE_NULL,                                                                        // pDynamicStates
1034         };
1035         const vk::VkGraphicsPipelineCreateInfo createInfo =
1036         {
1037                 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
1038                 DE_NULL,
1039                 shaderStages.getNumStages(),                                                                    // stageCount
1040                 shaderStages.getStages(),                                                                               // pStages
1041                 &vertexInputState,                                                                                              // pVertexInputState
1042                 &iaState,                                                                                                               // pInputAssemblyState
1043                 (shaderStages.hasTessellationStage() ? &tessState : DE_NULL),   // pTessellationState
1044                 &vpState,                                                                                                               // pViewportState
1045                 &rsState,                                                                                                               // pRasterState
1046                 &msState,                                                                                                               // pMultisampleState
1047                 &dsState,                                                                                                               // pDepthStencilState
1048                 &cbState,                                                                                                               // pColorBlendState
1049                 &dynState,                                                                                                              // pDynamicState
1050                 0u,                                                                                                                             // flags
1051                 pipelineLayout,                                                                                                 // layout
1052                 *m_renderPass,                                                                                                  // renderPass
1053                 0u,                                                                                                                             // subpass
1054                 (vk::VkPipeline)0,                                                                                              // basePipelineHandle
1055                 0u,                                                                                                                             // basePipelineIndex
1056         };
1057         return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo);
1058 }
1059
1060 void SingleCmdRenderInstance::renderToTarget (void)
1061 {
1062         const vk::VkRect2D                                                                      renderArea                                      =
1063         {
1064                 { 0, 0 },                                                                                                       // offset
1065                 { (deInt32)m_targetSize.x(), (deInt32)m_targetSize.y() },       // extent
1066         };
1067         const vk::VkCmdBufferCreateInfo                                         mainCmdBufCreateInfo                    =
1068         {
1069                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
1070                 DE_NULL,
1071                 *m_cmdPool,                                                     // cmdPool
1072                 vk::VK_CMD_BUFFER_LEVEL_PRIMARY,        // level
1073                 0u,                                                                     // flags
1074         };
1075         const vk::VkCmdBufferBeginInfo                                          mainCmdBufBeginInfo                             =
1076         {
1077                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
1078                 DE_NULL,
1079                 vk::VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | vk::VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,    // flags
1080                 (vk::VkRenderPass)0u,                                                                                                                                                   // renderPass
1081                 0u,                                                                                                                                                                                             // subpass
1082                 (vk::VkFramebuffer)0u,                                                                                                                                                  // framebuffer
1083         };
1084         const vk::VkCmdBufferCreateInfo                                         passCmdBufCreateInfo                    =
1085         {
1086                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
1087                 DE_NULL,
1088                 *m_cmdPool,                                                     // cmdPool
1089                 vk::VK_CMD_BUFFER_LEVEL_SECONDARY,      // level
1090                 0u,                                                                     // flags
1091         };
1092         const vk::VkCmdBufferBeginInfo                                          passCmdBufBeginInfo                             =
1093         {
1094                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
1095                 DE_NULL,
1096                 vk::VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | vk::VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,    // flags
1097                 (vk::VkRenderPass)*m_renderPass,                                                                                                                                // renderPass
1098                 0u,                                                                                                                                                                                             // subpass
1099                 (vk::VkFramebuffer)*m_framebuffer,                                                                                                                              // framebuffer
1100         };
1101         const vk::VkFenceCreateInfo                                                     fenceCreateInfo                         =
1102         {
1103                 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1104                 DE_NULL,
1105                 0u,                     // flags
1106         };
1107         const vk::VkClearValue                                                          clearValue                                      = createClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
1108         const vk::VkRenderPassBeginInfo                                         renderPassBeginInfo                     =
1109         {
1110                 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1111                 DE_NULL,
1112                 *m_renderPass,          // renderPass
1113                 *m_framebuffer,         // framebuffer
1114                 renderArea,                     // renderArea
1115                 1u,                                     // clearValueCount
1116                 &clearValue,            // pClearValues
1117         };
1118
1119         const vk::VkPipelineLayout                                                      pipelineLayout                          (getPipelineLayout());
1120         const vk::Unique<vk::VkPipeline>                                        pipeline                                        (createPipeline(pipelineLayout));
1121         const vk::Unique<vk::VkCmdBuffer>                                       mainCmd                                         (vk::createCommandBuffer(m_vki, m_device, &mainCmdBufCreateInfo));
1122         const vk::Unique<vk::VkCmdBuffer>                                       passCmd                                         ((m_isPrimaryCmdBuf) ? (vk::Move<vk::VkCmdBuffer>()) : (vk::createCommandBuffer(m_vki, m_device, &passCmdBufCreateInfo)));
1123         const vk::Unique<vk::VkFence>                                           fence                                           (vk::createFence(m_vki, m_device, &fenceCreateInfo));
1124         const deUint64                                                                          infiniteTimeout                         = ~(deUint64)0u;
1125         const vk::VkRenderPassContents                                          passContents                            = (m_isPrimaryCmdBuf) ? (vk::VK_RENDER_PASS_CONTENTS_INLINE) : (vk::VK_RENDER_PASS_CONTENTS_SECONDARY_CMD_BUFFERS);
1126
1127         VK_CHECK(m_vki.beginCommandBuffer(*mainCmd, &mainCmdBufBeginInfo));
1128         m_vki.cmdBeginRenderPass(*mainCmd, &renderPassBeginInfo, passContents);
1129
1130         if (m_isPrimaryCmdBuf)
1131         {
1132                 m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1133                 writeDrawCmdBuffer(*mainCmd);
1134         }
1135         else
1136         {
1137                 VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo));
1138                 m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1139                 writeDrawCmdBuffer(*passCmd);
1140                 VK_CHECK(m_vki.endCommandBuffer(*passCmd));
1141
1142                 m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get());
1143         }
1144
1145         m_vki.cmdEndRenderPass(*mainCmd);
1146         VK_CHECK(m_vki.endCommandBuffer(*mainCmd));
1147
1148         // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no).
1149         VK_CHECK(m_vki.queueSubmit(m_queue, 1, &mainCmd.get(), *fence));
1150         VK_CHECK(m_vki.waitForFences(m_device, 1, &fence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
1151 }
1152
1153 enum ShaderInputInterface
1154 {
1155         SHADER_INPUT_SINGLE_DESCRIPTOR = 0,     //!< one descriptor
1156         SHADER_INPUT_MULTIPLE_DESCRIPTORS,      //!< multiple descriptors
1157         SHADER_INPUT_DESCRIPTOR_ARRAY,          //!< descriptor array
1158
1159         SHADER_INPUT_LAST
1160 };
1161
1162 deUint32 getInterfaceNumResources (ShaderInputInterface shaderInterface)
1163 {
1164         switch (shaderInterface)
1165         {
1166                 case SHADER_INPUT_SINGLE_DESCRIPTOR:    return 1u;
1167                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS: return 2u;
1168                 case SHADER_INPUT_DESCRIPTOR_ARRAY:             return 2u;
1169
1170                 default:
1171                         DE_FATAL("Impossible");
1172                         return 0u;
1173         }
1174 }
1175
1176 class BufferRenderInstance : public SingleCmdRenderInstance
1177 {
1178 public:
1179                                                                                                         BufferRenderInstance            (Context&                                       context,
1180                                                                                                                                                                  bool                                           isPrimaryCmdBuf,
1181                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
1182                                                                                                                                                                  vk::VkShaderStageFlags         stageFlags,
1183                                                                                                                                                                  ShaderInputInterface           shaderInterface,
1184                                                                                                                                                                  bool                                           viewOffset,
1185                                                                                                                                                                  bool                                           dynamicOffset,
1186                                                                                                                                                                  bool                                           dynamicOffsetNonZero);
1187
1188         static vk::Move<vk::VkBuffer>                                   createSourceBuffer                      (const vk::DeviceInterface&             vki,
1189                                                                                                                                                                  vk::VkDevice                                   device,
1190                                                                                                                                                                  vk::Allocator&                                 allocator,
1191                                                                                                                                                                  vk::VkDescriptorType                   descriptorType,
1192                                                                                                                                                                  deUint32                                               offset,
1193                                                                                                                                                                  deUint32                                               bufferSize,
1194                                                                                                                                                                  de::MovePtr<vk::Allocation>*   outMemory);
1195
1196         static vk::Move<vk::VkDescriptorPool>                   createDescriptorPool            (const vk::DeviceInterface&     vki,
1197                                                                                                                                                                  vk::VkDevice                           device,
1198                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
1199                                                                                                                                                                  ShaderInputInterface           shaderInterface);
1200
1201         static vk::Move<vk::VkDescriptorSetLayout>              createDescriptorSetLayout       (const vk::DeviceInterface&     vki,
1202                                                                                                                                                                  vk::VkDevice                           device,
1203                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
1204                                                                                                                                                                  ShaderInputInterface           shaderInterface,
1205                                                                                                                                                                  vk::VkShaderStageFlags         stageFlags);
1206
1207         static vk::Move<vk::VkDescriptorSet>                    createDescriptorSet                     (const vk::DeviceInterface&     vki,
1208                                                                                                                                                                  vk::VkDevice                           device,
1209                                                                                                                                                                  vk::VkDescriptorSetLayout      descriptorSetLayout,
1210                                                                                                                                                                  vk::VkDescriptorPool           descriptorPool,
1211                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
1212                                                                                                                                                                  ShaderInputInterface           shaderInterface,
1213                                                                                                                                                                  vk::VkBuffer                           sourceBufferA,
1214                                                                                                                                                                  const deUint32                         viewOffsetA,
1215                                                                                                                                                                  vk::VkBuffer                           sourceBufferB,
1216                                                                                                                                                                  const deUint32                         viewOffsetB);
1217
1218         static vk::Move<vk::VkPipelineLayout>                   createPipelineLayout            (const vk::DeviceInterface&     vki,
1219                                                                                                                                                                  vk::VkDevice                           device,
1220                                                                                                                                                                  vk::VkDescriptorSetLayout      descriptorSetLayout);
1221
1222         void                                                                                    logTestPlan                                     (void) const;
1223         vk::VkPipelineLayout                                                    getPipelineLayout                       (void) const;
1224         void                                                                                    writeDrawCmdBuffer                      (vk::VkCmdBuffer cmd) const;
1225         tcu::TestStatus                                                                 verifyResultImage                       (const tcu::ConstPixelBufferAccess& result) const;
1226
1227         enum
1228         {
1229                 RENDER_SIZE                             = 128,
1230                 BUFFER_DATA_SIZE                = 8 * sizeof(float),
1231                 BUFFER_SIZE_A                   = 2048, //!< a lot more than required
1232                 BUFFER_SIZE_B                   = 2560, //!< a lot more than required
1233
1234                 STATIC_OFFSET_VALUE_A   = 256,
1235                 DYNAMIC_OFFSET_VALUE_A  = 512,
1236                 STATIC_OFFSET_VALUE_B   = 1024,
1237                 DYNAMIC_OFFSET_VALUE_B  = 768,
1238         };
1239
1240         const vk::VkDescriptorType                                              m_descriptorType;
1241         const ShaderInputInterface                                              m_shaderInterface;
1242         const bool                                                                              m_setViewOffset;
1243         const bool                                                                              m_setDynamicOffset;
1244         const bool                                                                              m_dynamicOffsetNonZero;
1245         const vk::VkShaderStageFlags                                    m_stageFlags;
1246
1247         const deUint32                                                                  m_viewOffsetA;
1248         const deUint32                                                                  m_viewOffsetB;
1249         const deUint32                                                                  m_dynamicOffsetA;
1250         const deUint32                                                                  m_dynamicOffsetB;
1251         const deUint32                                                                  m_effectiveOffsetA;
1252         const deUint32                                                                  m_effectiveOffsetB;
1253         const deUint32                                                                  m_bufferSizeA;
1254         const deUint32                                                                  m_bufferSizeB;
1255
1256         de::MovePtr<vk::Allocation>                                             m_bufferMemoryA;
1257         de::MovePtr<vk::Allocation>                                             m_bufferMemoryB;
1258         const vk::Unique<vk::VkBuffer>                                  m_sourceBufferA;
1259         const vk::Unique<vk::VkBuffer>                                  m_sourceBufferB;
1260         const vk::Unique<vk::VkDescriptorPool>                  m_descriptorPool;
1261         const vk::Unique<vk::VkDescriptorSetLayout>             m_descriptorSetLayout;
1262         const vk::Unique<vk::VkDescriptorSet>                   m_descriptorSet;
1263         const vk::Unique<vk::VkPipelineLayout>                  m_pipelineLayout;
1264 };
1265
1266 BufferRenderInstance::BufferRenderInstance      (Context&                               context,
1267                                                                                          bool                                   isPrimaryCmdBuf,
1268                                                                                          vk::VkDescriptorType   descriptorType,
1269                                                                                          vk::VkShaderStageFlags stageFlags,
1270                                                                                          ShaderInputInterface   shaderInterface,
1271                                                                                          bool                                   viewOffset,
1272                                                                                          bool                                   dynamicOffset,
1273                                                                                          bool                                   dynamicOffsetNonZero)
1274         : SingleCmdRenderInstance               (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
1275         , m_descriptorType                              (descriptorType)
1276         , m_shaderInterface                             (shaderInterface)
1277         , m_setViewOffset                               (viewOffset)
1278         , m_setDynamicOffset                    (dynamicOffset)
1279         , m_dynamicOffsetNonZero                (dynamicOffsetNonZero)
1280         , m_stageFlags                                  (stageFlags)
1281         , m_viewOffsetA                                 ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u))
1282         , m_viewOffsetB                                 ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u))
1283         , m_dynamicOffsetA                              ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u))
1284         , m_dynamicOffsetB                              ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u))
1285         , m_effectiveOffsetA                    ((isDynamicDescriptorType(m_descriptorType)) ? (m_dynamicOffsetA) : (m_viewOffsetA))
1286         , m_effectiveOffsetB                    ((isDynamicDescriptorType(m_descriptorType)) ? (m_dynamicOffsetB) : (m_viewOffsetB))
1287         , m_bufferSizeA                                 (BUFFER_SIZE_A)
1288         , m_bufferSizeB                                 (BUFFER_SIZE_B)
1289         , m_bufferMemoryA                               (DE_NULL)
1290         , m_bufferMemoryB                               (DE_NULL)
1291         , m_sourceBufferA                               (createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetA, m_bufferSizeA, &m_bufferMemoryA))
1292         , m_sourceBufferB                               ((getInterfaceNumResources(m_shaderInterface) == 1u)
1293                                                                                 ? vk::Move<vk::VkBuffer>()
1294                                                                                 : createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetB, m_bufferSizeB, &m_bufferMemoryB))
1295         , m_descriptorPool                              (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
1296         , m_descriptorSetLayout                 (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
1297         , m_descriptorSet                               (createDescriptorSet(m_vki, m_device, *m_descriptorSetLayout, *m_descriptorPool, m_descriptorType, m_shaderInterface, *m_sourceBufferA, m_viewOffsetA, *m_sourceBufferB, m_viewOffsetB))
1298         , m_pipelineLayout                              (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
1299 {
1300         if (m_setDynamicOffset)
1301                 DE_ASSERT(isDynamicDescriptorType(m_descriptorType));
1302         if (m_dynamicOffsetNonZero)
1303                 DE_ASSERT(m_setDynamicOffset);
1304 }
1305
1306 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer (const vk::DeviceInterface&             vki,
1307                                                                                                                                  vk::VkDevice                                   device,
1308                                                                                                                                  vk::Allocator&                                 allocator,
1309                                                                                                                                  vk::VkDescriptorType                   descriptorType,
1310                                                                                                                                  deUint32                                               offset,
1311                                                                                                                                  deUint32                                               bufferSize,
1312                                                                                                                                  de::MovePtr<vk::Allocation>*   outMemory)
1313 {
1314         static const float                              s_colors[]                      =
1315         {
1316                 0.0f, 1.0f, 0.0f, 1.0f,         // green
1317                 1.0f, 1.0f, 0.0f, 1.0f,         // yellow
1318         };
1319         DE_STATIC_ASSERT(sizeof(s_colors) == BUFFER_DATA_SIZE);
1320         DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize);
1321         DE_ASSERT(offset % sizeof(float) == 0);
1322         DE_ASSERT(bufferSize % sizeof(float) == 0);
1323
1324         const bool                                              isUniformBuffer         = isUniformDescriptorType(descriptorType);
1325         const vk::VkBufferUsageFlags    usageFlags                      = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1326         const float                                             preGuardValue           = 0.5f;
1327         const float                                             postGuardValue          = 0.75f;
1328         const vk::VkBufferCreateInfo    bufferCreateInfo        =
1329         {
1330                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1331                 DE_NULL,
1332                 bufferSize,                                             // size
1333                 usageFlags,                                             // usage
1334                 0u,                                                             // flags
1335                 vk::VK_SHARING_MODE_EXCLUSIVE,  // sharingMode
1336                 0u,                                                             // queueFamilyCount
1337                 DE_NULL,                                                // pQueueFamilyIndices
1338         };
1339         vk::Move<vk::VkBuffer>                  buffer                          (vk::createBuffer(vki, device, &bufferCreateInfo));
1340         de::MovePtr<vk::Allocation>             bufferMemory            = allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible);
1341         void* const                                             mapPtr                          = bufferMemory->getHostPtr();
1342
1343         // guard with interesting values
1344         for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float))
1345                 deMemcpy((deUint8*)mapPtr + preGuardOffset, &preGuardValue, sizeof(float));
1346
1347         deMemcpy((deUint8*)mapPtr + offset, s_colors, sizeof(s_colors));
1348         for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors); postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float))
1349                 deMemcpy((deUint8*)mapPtr + postGuardOffset, &postGuardValue, sizeof(float));
1350         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
1351
1352         flushMappedMemoryRange(vki, device, bufferMemory->getMemory(), bufferMemory->getOffset(), bufferSize);
1353
1354         *outMemory = bufferMemory;
1355         return buffer;
1356 }
1357
1358 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool (const vk::DeviceInterface&   vki,
1359                                                                                                                                                    vk::VkDevice                                 device,
1360                                                                                                                                                    vk::VkDescriptorType                 descriptorType,
1361                                                                                                                                                    ShaderInputInterface                 shaderInterface)
1362 {
1363         return vk::DescriptorPoolBuilder()
1364                 .addType(descriptorType, getInterfaceNumResources(shaderInterface))
1365                 .build(vki, device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
1366 }
1367
1368 vk::Move<vk::VkDescriptorSetLayout> BufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki,
1369                                                                                                                                                                          vk::VkDevice                           device,
1370                                                                                                                                                                          vk::VkDescriptorType           descriptorType,
1371                                                                                                                                                                          ShaderInputInterface           shaderInterface,
1372                                                                                                                                                                          vk::VkShaderStageFlags         stageFlags)
1373 {
1374         vk::DescriptorSetLayoutBuilder builder;
1375
1376         switch (shaderInterface)
1377         {
1378                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1379                         builder.addSingleBinding(descriptorType, stageFlags);
1380                         break;
1381
1382                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
1383                         builder.addSingleBinding(descriptorType, stageFlags);
1384                         builder.addSingleBinding(descriptorType, stageFlags);
1385                         break;
1386
1387                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1388                         builder.addArrayBinding(descriptorType, 2u, stageFlags);
1389                         break;
1390
1391                 default:
1392                         DE_FATAL("Impossible");
1393         }
1394
1395         return builder.build(vki, device);
1396 }
1397
1398 vk::Move<vk::VkDescriptorSet> BufferRenderInstance::createDescriptorSet (const vk::DeviceInterface&     vki,
1399                                                                                                                                                  vk::VkDevice                           device,
1400                                                                                                                                                  vk::VkDescriptorSetLayout      descriptorSetLayout,
1401                                                                                                                                                  vk::VkDescriptorPool           descriptorPool,
1402                                                                                                                                                  vk::VkDescriptorType           descriptorType,
1403                                                                                                                                                  ShaderInputInterface           shaderInterface,
1404                                                                                                                                                  vk::VkBuffer                           bufferA,
1405                                                                                                                                                  deUint32                                       offsetA,
1406                                                                                                                                                  vk::VkBuffer                           bufferB,
1407                                                                                                                                                  deUint32                                       offsetB)
1408 {
1409         const vk::VkDescriptorInfo              bufferInfos[2]  =
1410         {
1411                 createDescriptorInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1412                 createDescriptorInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE),
1413         };
1414
1415         vk::Move<vk::VkDescriptorSet>   descriptorSet   = allocDescriptorSet(vki, device, descriptorPool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, descriptorSetLayout);
1416         vk::DescriptorSetUpdateBuilder  builder;
1417
1418         switch (shaderInterface)
1419         {
1420                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1421                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
1422                         break;
1423
1424                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
1425                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]);
1426                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &bufferInfos[1]);
1427                         break;
1428
1429                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
1430                         builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, bufferInfos);
1431                         break;
1432
1433                 default:
1434                         DE_FATAL("Impossible");
1435         }
1436
1437         builder.update(vki, device);
1438         return descriptorSet;
1439 }
1440
1441 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout (const vk::DeviceInterface&   vki,
1442                                                                                                                                                    vk::VkDevice                                 device,
1443                                                                                                                                                    vk::VkDescriptorSetLayout    descriptorSetLayout)
1444 {
1445         const vk::VkPipelineLayoutCreateInfo createInfo =
1446         {
1447                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1448                 DE_NULL,
1449                 1,                                              // descriptorSetCount
1450                 &descriptorSetLayout,   // pSetLayouts
1451                 0u,                                             // pushConstantRangeCount
1452                 DE_NULL,                                // pPushConstantRanges
1453         };
1454
1455         return vk::createPipelineLayout(vki, device, &createInfo);
1456 }
1457
1458 void BufferRenderInstance::logTestPlan (void) const
1459 {
1460         std::ostringstream msg;
1461
1462         msg << "Rendering 2x2 yellow-green grid.\n"
1463                 << "Single descriptor set. Descriptor set contains "
1464                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
1465                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
1466                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
1467                             (const char*)DE_NULL)
1468                 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
1469                 << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
1470
1471         if (isDynamicDescriptorType(m_descriptorType))
1472         {
1473                 if (m_setDynamicOffset)
1474                 {
1475                         msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
1476                                 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
1477                 }
1478                 else
1479                 {
1480                         msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
1481                 }
1482         }
1483
1484         if (m_stageFlags == 0u)
1485         {
1486                 msg << "Descriptors are not accessed in any shader stage.\n";
1487         }
1488         else
1489         {
1490                 msg << "Descriptors are accessed in {"
1491                         << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)                      ? (" vertex")                   : (""))
1492                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0)        ? (" tess_control")             : (""))
1493                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0)     ? (" tess_evaluation")  : (""))
1494                         << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)            ? (" geometry")                 : (""))
1495                         << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)            ? (" fragment")                 : (""))
1496                         << " } stages.\n";
1497         }
1498
1499         m_context.getTestContext().getLog()
1500                 << tcu::TestLog::Message
1501                 << msg.str()
1502                 << tcu::TestLog::EndMessage;
1503 }
1504
1505 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout (void) const
1506 {
1507         return *m_pipelineLayout;
1508 }
1509
1510 void BufferRenderInstance::writeDrawCmdBuffer (vk::VkCmdBuffer cmd) const
1511 {
1512         const bool                                                      isUniformBuffer         = isUniformDescriptorType(m_descriptorType);
1513
1514         // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset
1515         const deUint32                                          dynamicOffsets[]        =
1516         {
1517                 m_dynamicOffsetA,
1518                 m_dynamicOffsetB,
1519         };
1520         const deUint32                                          numOffsets                      = (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface));
1521         const deUint32* const                           dynamicOffsetPtr        = (!m_setDynamicOffset) ? (DE_NULL) : (dynamicOffsets);
1522
1523         // make host writes device-visible
1524         const vk::VkMemoryInputFlags            inputBit                        = (isUniformBuffer) ? (vk::VK_MEMORY_INPUT_UNIFORM_READ_BIT) : (vk::VK_MEMORY_INPUT_SHADER_READ_BIT);
1525         const vk::VkBufferMemoryBarrier         memoryBarrierA          =
1526         {
1527                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1528                 DE_NULL,
1529                 vk::VK_MEMORY_OUTPUT_HOST_WRITE_BIT,            // outputMask
1530                 inputBit,                                                                       // inputMask
1531                 vk::VK_QUEUE_FAMILY_IGNORED,                            // srcQueueFamilyIndex
1532                 vk::VK_QUEUE_FAMILY_IGNORED,                            // destQueueFamilyIndex
1533                 *m_sourceBufferA,                                                       // buffer
1534                 0u,                                                                                     // offset
1535                 (vk::VkDeviceSize)m_bufferSizeA,                        // size
1536         };
1537         const vk::VkBufferMemoryBarrier         memoryBarrierB          =
1538         {
1539                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1540                 DE_NULL,
1541                 vk::VK_MEMORY_OUTPUT_HOST_WRITE_BIT,            // outputMask
1542                 inputBit,                                                                       // inputMask
1543                 vk::VK_QUEUE_FAMILY_IGNORED,                            // srcQueueFamilyIndex
1544                 vk::VK_QUEUE_FAMILY_IGNORED,                            // destQueueFamilyIndex
1545                 *m_sourceBufferB,                                                       // buffer
1546                 0u,                                                                                     // offset
1547                 (vk::VkDeviceSize)m_bufferSizeB,                        // size
1548         };
1549         const void* const                                       memoryBarriers[2]       =
1550         {
1551                 &memoryBarrierA,
1552                 &memoryBarrierB,
1553         };
1554         const deUint32                                          numMemoryBarriers       = getInterfaceNumResources(m_shaderInterface);
1555
1556         m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), numOffsets, dynamicOffsetPtr);
1557         m_vki.cmdPipelineBarrier(cmd, 0u, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS, vk::VK_FALSE, numMemoryBarriers, memoryBarriers);
1558         m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
1559 }
1560
1561 tcu::TestStatus BufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
1562 {
1563         const tcu::Vec4         green           (0.0f, 1.0f, 0.0f, 1.0f);
1564         const tcu::Vec4         yellow          (1.0f, 1.0f, 0.0f, 1.0f);
1565         tcu::Surface            reference       (m_targetSize.x(), m_targetSize.y());
1566
1567         drawQuadrantReferenceResult(reference.getAccess(), yellow, green, green, yellow);
1568
1569         if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
1570                 return tcu::TestStatus::fail("Image verification failed");
1571         else
1572                 return tcu::TestStatus::pass("Pass");
1573 }
1574
1575 class ComputeInstanceResultBuffer
1576 {
1577 public:
1578         enum
1579         {
1580                 DATA_SIZE = sizeof(tcu::Vec4[4])
1581         };
1582
1583                                                                                         ComputeInstanceResultBuffer     (const vk::DeviceInterface&             vki,
1584                                                                                                                                                  vk::VkDevice                                   device,
1585                                                                                                                                                  vk::Allocator&                                 allocator);
1586
1587         void                                                                    readResultContentsTo            (tcu::Vec4 (*results)[4]) const;
1588
1589         inline vk::VkBuffer                                             getBuffer                                       (void) const { return *m_buffer;                        }
1590         inline const void*                                              getResultReadBarrier            (void) const { return &m_bufferBarrier;         }
1591
1592 private:
1593         static vk::Move<vk::VkBuffer>                   createResultBuffer                      (const vk::DeviceInterface&             vki,
1594                                                                                                                                                  vk::VkDevice                                   device,
1595                                                                                                                                                  vk::Allocator&                                 allocator,
1596                                                                                                                                                  de::MovePtr<vk::Allocation>*   outAllocation);
1597
1598         static vk::VkBufferMemoryBarrier                createResultBufferBarrier       (vk::VkBuffer buffer);
1599
1600         const vk::DeviceInterface&                              m_vki;
1601         const vk::VkDevice                                              m_device;
1602
1603         de::MovePtr<vk::Allocation>                             m_bufferMem;
1604         const vk::Unique<vk::VkBuffer>                  m_buffer;
1605         const vk::VkBufferMemoryBarrier                 m_bufferBarrier;
1606 };
1607
1608 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const vk::DeviceInterface&    vki,
1609                                                                                                                   vk::VkDevice                                  device,
1610                                                                                                                   vk::Allocator&                                allocator)
1611         : m_vki                         (vki)
1612         , m_device                      (device)
1613         , m_bufferMem           (DE_NULL)
1614         , m_buffer                      (createResultBuffer(m_vki, m_device, allocator, &m_bufferMem))
1615         , m_bufferBarrier       (createResultBufferBarrier(*m_buffer))
1616 {
1617 }
1618
1619 void ComputeInstanceResultBuffer::readResultContentsTo (tcu::Vec4 (*results)[4]) const
1620 {
1621         invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*results));
1622         deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
1623 }
1624
1625 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer (const vk::DeviceInterface&              vki,
1626                                                                                                                                                 vk::VkDevice                                    device,
1627                                                                                                                                                 vk::Allocator&                                  allocator,
1628                                                                                                                                                 de::MovePtr<vk::Allocation>*    outAllocation)
1629 {
1630         const vk::VkBufferCreateInfo    createInfo      =
1631         {
1632                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1633                 DE_NULL,
1634                 (vk::VkDeviceSize)DATA_SIZE,                            // size
1635                 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,         // usage
1636                 0u,                                                                                     // flags
1637                 vk::VK_SHARING_MODE_EXCLUSIVE,                          // sharingMode
1638                 0u,                                                                                     // queueFamilyCount
1639                 DE_NULL,                                                                        // pQueueFamilyIndices
1640         };
1641         vk::Move<vk::VkBuffer>                  buffer          (vk::createBuffer(vki, device, &createInfo));
1642         de::MovePtr<vk::Allocation>             allocation      (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
1643         const float                                             clearValue      = -1.0f;
1644         void*                                                   mapPtr          = allocation->getHostPtr();
1645
1646         for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
1647                 deMemcpy(((deUint8*)mapPtr) + offset, &clearValue, sizeof(float));
1648
1649         flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), (vk::VkDeviceSize)DATA_SIZE);
1650
1651         *outAllocation = allocation;
1652         return buffer;
1653 }
1654
1655 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier (vk::VkBuffer buffer)
1656 {
1657         const vk::VkBufferMemoryBarrier bufferBarrier =
1658         {
1659                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1660                 DE_NULL,
1661                 vk::VK_MEMORY_OUTPUT_SHADER_WRITE_BIT,          // outputMask
1662                 vk::VK_MEMORY_INPUT_HOST_READ_BIT,                      // inputMask
1663                 vk::VK_QUEUE_FAMILY_IGNORED,                            // srcQueueFamilyIndex
1664                 vk::VK_QUEUE_FAMILY_IGNORED,                            // destQueueFamilyIndex
1665                 buffer,                                                                         // buffer
1666                 (vk::VkDeviceSize)0u,                                           // offset
1667                 DATA_SIZE,                                                                      // size
1668         };
1669         return bufferBarrier;
1670 }
1671
1672 class ComputePipeline
1673 {
1674 public:
1675                                                                                         ComputePipeline                 (const vk::DeviceInterface&                     vki,
1676                                                                                                                                          vk::VkDevice                                           device,
1677                                                                                                                                          const vk::BinaryCollection&            programCollection,
1678                                                                                                                                          deUint32                                                       numDescriptorSets,
1679                                                                                                                                          const vk::VkDescriptorSetLayout*       descriptorSetLayouts);
1680
1681         inline vk::VkPipeline                                   getPipeline                             (void) const { return *m_pipeline;                      };
1682         inline vk::VkPipelineLayout                             getPipelineLayout               (void) const { return *m_pipelineLayout;        };
1683
1684 private:
1685         static vk::Move<vk::VkPipelineLayout>   createPipelineLayout    (const vk::DeviceInterface&                     vki,
1686                                                                                                                                          vk::VkDevice                                           device,
1687                                                                                                                                          deUint32                                                       numDescriptorSets,
1688                                                                                                                                          const vk::VkDescriptorSetLayout*       descriptorSetLayouts);
1689
1690         static vk::Move<vk::VkPipeline>                 createPipeline                  (const vk::DeviceInterface&                     vki,
1691                                                                                                                                          vk::VkDevice                                           device,
1692                                                                                                                                          const vk::BinaryCollection&            programCollection,
1693                                                                                                                                          vk::VkPipelineLayout                           layout);
1694
1695         const vk::Unique<vk::VkPipelineLayout>  m_pipelineLayout;
1696         const vk::Unique<vk::VkPipeline>                m_pipeline;
1697 };
1698
1699 ComputePipeline::ComputePipeline (const vk::DeviceInterface&            vki,
1700                                                                   vk::VkDevice                                          device,
1701                                                                   const vk::BinaryCollection&           programCollection,
1702                                                                   deUint32                                                      numDescriptorSets,
1703                                                                   const vk::VkDescriptorSetLayout*      descriptorSetLayouts)
1704         : m_pipelineLayout      (createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts))
1705         , m_pipeline            (createPipeline(vki, device, programCollection, *m_pipelineLayout))
1706 {
1707 }
1708
1709 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout (const vk::DeviceInterface&                vki,
1710                                                                                                                                           vk::VkDevice                                          device,
1711                                                                                                                                           deUint32                                                      numDescriptorSets,
1712                                                                                                                                           const vk::VkDescriptorSetLayout*      descriptorSetLayouts)
1713 {
1714         const vk::VkPipelineLayoutCreateInfo createInfo =
1715         {
1716                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1717                 DE_NULL,
1718                 numDescriptorSets,              // descriptorSetCount
1719                 descriptorSetLayouts,   // pSetLayouts
1720                 0u,                                             // pushConstantRangeCount
1721                 DE_NULL,                                // pPushConstantRanges
1722         };
1723         return vk::createPipelineLayout(vki, device, &createInfo);
1724 }
1725
1726 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline (const vk::DeviceInterface&    vki,
1727                                                                                                                   vk::VkDevice                                  device,
1728                                                                                                                   const vk::BinaryCollection&   programCollection,
1729                                                                                                                   vk::VkPipelineLayout                  layout)
1730 {
1731         const vk::Unique<vk::VkShaderModule>            computeModule           (vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u));
1732         const vk::VkShaderCreateInfo                            shaderCreateInfo        =
1733         {
1734                 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
1735                 DE_NULL,
1736                 *computeModule,         // module
1737                 "main",                         // pName
1738                 0u,                                     // flags
1739                 vk::VK_SHADER_STAGE_COMPUTE
1740         };
1741         const vk::Unique<vk::VkShader>                          computeShader           (vk::createShader(vki, device, &shaderCreateInfo));
1742         const vk::VkPipelineShaderStageCreateInfo       cs                                      =
1743         {
1744                 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1745                 DE_NULL,
1746                 vk::VK_SHADER_STAGE_COMPUTE,    // stage
1747                 *computeShader,                                 // shader
1748                 DE_NULL,                                                // pSpecializationInfo
1749         };
1750         const vk::VkComputePipelineCreateInfo           createInfo                      =
1751         {
1752                 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1753                 DE_NULL,
1754                 cs,                                                             // cs
1755                 0u,                                                             // flags
1756                 layout,                                                 // layout
1757                 (vk::VkPipeline)0,                              // basePipelineHandle
1758                 0u,                                                             // basePipelineIndex
1759         };
1760         return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo);
1761 }
1762
1763 class ComputeCommand
1764 {
1765 public:
1766                                                                                 ComputeCommand  (const vk::DeviceInterface&     vki,
1767                                                                                                                  vk::VkDevice                           device,
1768                                                                                                                  vk::VkPipeline                         pipeline,
1769                                                                                                                  vk::VkPipelineLayout           pipelineLayout,
1770                                                                                                                  const tcu::UVec3&                      numWorkGroups,
1771                                                                                                                  int                                            numDescriptorSets,
1772                                                                                                                  const vk::VkDescriptorSet*     descriptorSets,
1773                                                                                                                  int                                            numDynamicOffsets,
1774                                                                                                                  const deUint32*                        dynamicOffsets,
1775                                                                                                                  int                                            numPreBarriers,
1776                                                                                                                  const void* const*                     preBarriers,
1777                                                                                                                  int                                            numPostBarriers,
1778                                                                                                                  const void* const*                     postBarriers);
1779
1780         void                                                            submitAndWait   (deUint32 queueFamilyIndex, vk::VkQueue queue) const;
1781
1782 private:
1783         const vk::DeviceInterface&                      m_vki;
1784         const vk::VkDevice                                      m_device;
1785         const vk::VkPipeline                            m_pipeline;
1786         const vk::VkPipelineLayout                      m_pipelineLayout;
1787         const tcu::UVec3&                                       m_numWorkGroups;
1788         const int                                                       m_numDescriptorSets;
1789         const vk::VkDescriptorSet* const        m_descriptorSets;
1790         const int                                                       m_numDynamicOffsets;
1791         const deUint32* const                           m_dynamicOffsets;
1792         const int                                                       m_numPreBarriers;
1793         const void* const* const                        m_preBarriers;
1794         const int                                                       m_numPostBarriers;
1795         const void* const* const                        m_postBarriers;
1796 };
1797
1798 ComputeCommand::ComputeCommand (const vk::DeviceInterface&      vki,
1799                                                                 vk::VkDevice                            device,
1800                                                                 vk::VkPipeline                          pipeline,
1801                                                                 vk::VkPipelineLayout            pipelineLayout,
1802                                                                 const tcu::UVec3&                       numWorkGroups,
1803                                                                 int                                                     numDescriptorSets,
1804                                                                 const vk::VkDescriptorSet*      descriptorSets,
1805                                                                 int                                                     numDynamicOffsets,
1806                                                                 const deUint32*                         dynamicOffsets,
1807                                                                 int                                                     numPreBarriers,
1808                                                                 const void* const*                      preBarriers,
1809                                                                 int                                                     numPostBarriers,
1810                                                                 const void* const*                      postBarriers)
1811         : m_vki                                 (vki)
1812         , m_device                              (device)
1813         , m_pipeline                    (pipeline)
1814         , m_pipelineLayout              (pipelineLayout)
1815         , m_numWorkGroups               (numWorkGroups)
1816         , m_numDescriptorSets   (numDescriptorSets)
1817         , m_descriptorSets              (descriptorSets)
1818         , m_numDynamicOffsets   (numDynamicOffsets)
1819         , m_dynamicOffsets              (dynamicOffsets)
1820         , m_numPreBarriers              (numPreBarriers)
1821         , m_preBarriers                 (preBarriers)
1822         , m_numPostBarriers             (numPostBarriers)
1823         , m_postBarriers                (postBarriers)
1824 {
1825 }
1826
1827 void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue) const
1828 {
1829         const vk::VkCmdPoolCreateInfo                                   cmdPoolCreateInfo       =
1830         {
1831                 vk::VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,
1832                 DE_NULL,
1833                 queueFamilyIndex,                                               // queueFamilyIndex
1834                 vk::VK_CMD_POOL_CREATE_TRANSIENT_BIT,   // flags
1835         };
1836         const vk::Unique<vk::VkCmdPool>                                 cmdPool                         (vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
1837
1838         const vk::VkFenceCreateInfo                                             fenceCreateInfo         =
1839         {
1840                 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1841                 DE_NULL,
1842                 0u,                     // flags
1843         };
1844
1845         const vk::VkCmdBufferCreateInfo                                 cmdBufCreateInfo        =
1846         {
1847                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
1848                 DE_NULL,
1849                 *cmdPool,                                                       // cmdPool
1850                 vk::VK_CMD_BUFFER_LEVEL_PRIMARY,        // level
1851                 0u,                                                                     // flags
1852         };
1853         const vk::VkCmdBufferBeginInfo                                  cmdBufBeginInfo         =
1854         {
1855                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
1856                 DE_NULL,
1857                 vk::VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | vk::VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,    // flags
1858                 (vk::VkRenderPass)0u,                                                                                                                                                   // renderPass
1859                 0u,                                                                                                                                                                                             // subpass
1860                 (vk::VkFramebuffer)0u,                                                                                                                                                  // framebuffer
1861         };
1862
1863         const vk::Unique<vk::VkFence>                                   cmdCompleteFence        (vk::createFence(m_vki, m_device, &fenceCreateInfo));
1864         const vk::Unique<vk::VkCmdBuffer>                               cmd                                     (vk::createCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
1865         const deUint64                                                                  infiniteTimeout         = ~(deUint64)0u;
1866
1867         VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
1868
1869         m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline);
1870         m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets);
1871
1872         if (m_numPreBarriers)
1873                 m_vki.cmdPipelineBarrier(*cmd, 0u, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_FALSE, m_numPreBarriers, m_preBarriers);
1874
1875         m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
1876         m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, m_numPostBarriers, m_postBarriers);
1877         VK_CHECK(m_vki.endCommandBuffer(*cmd));
1878
1879         // run
1880         VK_CHECK(m_vki.queueSubmit(queue, 1, &cmd.get(), *cmdCompleteFence));
1881         VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
1882 }
1883
1884 class BufferComputeInstance : public vkt::TestInstance
1885 {
1886 public:
1887                                                                                         BufferComputeInstance           (Context&                               context,
1888                                                                                                                                                  vk::VkDescriptorType   descriptorType,
1889                                                                                                                                                  ShaderInputInterface   shaderInterface,
1890                                                                                                                                                  bool                                   viewOffset,
1891                                                                                                                                                  bool                                   dynamicOffset,
1892                                                                                                                                                  bool                                   dynamicOffsetNonZero);
1893
1894 private:
1895         vk::Move<vk::VkBuffer>                                  createColorDataBuffer           (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation);
1896         vk::Move<vk::VkBufferView>                              createBufferView                        (vk::VkBuffer buffer, deUint32 offset) const;
1897         vk::Move<vk::VkDescriptorSetLayout>             createDescriptorSetLayout       (void) const;
1898         vk::Move<vk::VkDescriptorPool>                  createDescriptorPool            (void) const;
1899         vk::Move<vk::VkDescriptorSet>                   createDescriptorSet                     (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) const;
1900
1901         tcu::TestStatus                                                 iterate                                         (void);
1902         void                                                                    logTestPlan                                     (void) const;
1903         tcu::TestStatus                                                 testResourceAccess                      (void);
1904
1905         enum
1906         {
1907                 STATIC_OFFSET_VALUE_A   = 256,
1908                 DYNAMIC_OFFSET_VALUE_A  = 512,
1909                 STATIC_OFFSET_VALUE_B   = 1024,
1910                 DYNAMIC_OFFSET_VALUE_B  = 768,
1911         };
1912
1913         const vk::VkDescriptorType                              m_descriptorType;
1914         const ShaderInputInterface                              m_shaderInterface;
1915         const bool                                                              m_setViewOffset;
1916         const bool                                                              m_setDynamicOffset;
1917         const bool                                                              m_dynamicOffsetNonZero;
1918
1919         const vk::DeviceInterface&                              m_vki;
1920         const vk::VkDevice                                              m_device;
1921         const vk::VkQueue                                               m_queue;
1922         const deUint32                                                  m_queueFamilyIndex;
1923         vk::Allocator&                                                  m_allocator;
1924
1925         const ComputeInstanceResultBuffer               m_result;
1926 };
1927
1928 BufferComputeInstance::BufferComputeInstance (Context&                                  context,
1929                                                                                           vk::VkDescriptorType          descriptorType,
1930                                                                                           ShaderInputInterface          shaderInterface,
1931                                                                                           bool                                          viewOffset,
1932                                                                                           bool                                          dynamicOffset,
1933                                                                                           bool                                          dynamicOffsetNonZero)
1934         : vkt::TestInstance                     (context)
1935         , m_descriptorType                      (descriptorType)
1936         , m_shaderInterface                     (shaderInterface)
1937         , m_setViewOffset                       (viewOffset)
1938         , m_setDynamicOffset            (dynamicOffset)
1939         , m_dynamicOffsetNonZero        (dynamicOffsetNonZero)
1940         , m_vki                                         (context.getDeviceInterface())
1941         , m_device                                      (context.getDevice())
1942         , m_queue                                       (context.getUniversalQueue())
1943         , m_queueFamilyIndex            (context.getUniversalQueueFamilyIndex())
1944         , m_allocator                           (context.getDefaultAllocator())
1945         , m_result                                      (m_vki, m_device, m_allocator)
1946 {
1947         if (m_dynamicOffsetNonZero)
1948                 DE_ASSERT(m_setDynamicOffset);
1949 }
1950
1951 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation)
1952 {
1953         DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
1954
1955         const bool                                              isUniformBuffer         = isUniformDescriptorType(m_descriptorType);
1956         const vk::VkBufferUsageFlags    usageFlags                      = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1957         const vk::VkBufferCreateInfo    createInfo =
1958         {
1959                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1960                 DE_NULL,
1961                 (vk::VkDeviceSize)bufferSize,   // size
1962                 usageFlags,                                             // usage
1963                 0u,                                                             // flags
1964                 vk::VK_SHARING_MODE_EXCLUSIVE,  // sharingMode
1965                 0u,                                                             // queueFamilyCount
1966                 DE_NULL,                                                // pQueueFamilyIndices
1967         };
1968         vk::Move<vk::VkBuffer>                  buffer                          (vk::createBuffer(m_vki, m_device, &createInfo));
1969         de::MovePtr<vk::Allocation>             allocation                      (allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
1970         void*                                                   mapPtr                          = allocation->getHostPtr();
1971
1972         if (offset)
1973                 deMemset(mapPtr, 0x5A, (size_t)offset);
1974         deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
1975         deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
1976         deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
1977
1978         flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize);
1979
1980         *outAllocation = allocation;
1981         return buffer;
1982 }
1983
1984 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout (void) const
1985 {
1986         vk::DescriptorSetLayoutBuilder builder;
1987
1988         builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1989
1990         switch (m_shaderInterface)
1991         {
1992                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
1993                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1994                         break;
1995
1996                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
1997                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1998                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1999                         break;
2000
2001                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2002                         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
2003                         break;
2004
2005                 default:
2006                         DE_FATAL("Impossible");
2007         };
2008
2009         return builder.build(m_vki, m_device);
2010 }
2011
2012 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool (void) const
2013 {
2014         return vk::DescriptorPoolBuilder()
2015                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2016                 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
2017                 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
2018 }
2019
2020 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) const
2021 {
2022         const vk::VkDescriptorInfo              resultInfo              = createDescriptorInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
2023         const vk::VkDescriptorInfo              bufferInfos[2]  =
2024         {
2025                 createDescriptorInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2026                 createDescriptorInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
2027         };
2028
2029         vk::Move<vk::VkDescriptorSet>   descriptorSet   = allocDescriptorSet(m_vki, m_device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
2030         vk::DescriptorSetUpdateBuilder  builder;
2031
2032         // result
2033         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
2034
2035         // buffers
2036         switch (m_shaderInterface)
2037         {
2038                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2039                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
2040                         break;
2041
2042                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
2043                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]);
2044                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &bufferInfos[1]);
2045                         break;
2046
2047                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2048                         builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, bufferInfos);
2049                         break;
2050
2051                 default:
2052                         DE_FATAL("Impossible");
2053         }
2054
2055         builder.update(m_vki, m_device);
2056         return descriptorSet;
2057 }
2058
2059 tcu::TestStatus BufferComputeInstance::iterate (void)
2060 {
2061         logTestPlan();
2062         return testResourceAccess();
2063 }
2064
2065 void BufferComputeInstance::logTestPlan (void) const
2066 {
2067         std::ostringstream msg;
2068
2069         msg << "Accessing resource in a compute program.\n"
2070                 << "Single descriptor set. Descriptor set contains "
2071                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
2072                                 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
2073                                 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
2074                                 (const char*)DE_NULL)
2075                 << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType)
2076                 << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n"
2077                 << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n";
2078
2079         if (isDynamicDescriptorType(m_descriptorType))
2080         {
2081                 if (m_setDynamicOffset)
2082                 {
2083                         msg << "Source buffer(s) are given a dynamic offset at bind time.\n"
2084                                 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n";
2085                 }
2086                 else
2087                 {
2088                         msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n";
2089                 }
2090         }
2091
2092         msg << "Destination buffer is pre-initialized to -1.\n";
2093
2094         m_context.getTestContext().getLog()
2095                 << tcu::TestLog::Message
2096                 << msg.str()
2097                 << tcu::TestLog::EndMessage;
2098 }
2099
2100 tcu::TestStatus BufferComputeInstance::testResourceAccess (void)
2101 {
2102         enum
2103         {
2104                 ADDRESSABLE_SIZE = 256, // allocate a lot more than required
2105         };
2106
2107         const bool                                                                              isDynamicCase           = isDynamicDescriptorType(m_descriptorType);
2108         const bool                                                                              isUniformBuffer         = isUniformDescriptorType(m_descriptorType);
2109         const deUint32                                                                  bindTimeOffsets[]       =
2110         {
2111                 (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u),
2112                 (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u),
2113         };
2114
2115         const tcu::Vec4                                                                 colorA1                         = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2116         const tcu::Vec4                                                                 colorA2                         = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
2117         const tcu::Vec4                                                                 colorB1                         = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2118         const tcu::Vec4                                                                 colorB2                         = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2119
2120         const deUint32                                                                  dataOffsetA                     = (isDynamicCase) ? (bindTimeOffsets[0]) : (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
2121         const deUint32                                                                  dataOffsetB                     = (isDynamicCase) ? (bindTimeOffsets[1]) : (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
2122         const deUint32                                                                  viewOffsetA                     = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u);
2123         const deUint32                                                                  viewOffsetB                     = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u);
2124         const deUint32                                                                  bufferSizeA                     = dataOffsetA + ADDRESSABLE_SIZE;
2125         const deUint32                                                                  bufferSizeB                     = dataOffsetB + ADDRESSABLE_SIZE;
2126
2127         de::MovePtr<vk::Allocation>                                             bufferMemA;
2128         const vk::Unique<vk::VkBuffer>                                  bufferA                         (createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA));
2129
2130         de::MovePtr<vk::Allocation>                                             bufferMemB;
2131         const vk::Unique<vk::VkBuffer>                                  bufferB                         ((getInterfaceNumResources(m_shaderInterface) == 1u)
2132                                                                                                                                                         ? (vk::Move<vk::VkBuffer>())
2133                                                                                                                                                         : (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB)));
2134
2135         const vk::Unique<vk::VkDescriptorSetLayout>             descriptorSetLayout     (createDescriptorSetLayout());
2136         const vk::Unique<vk::VkDescriptorPool>                  descriptorPool          (createDescriptorPool());
2137         const vk::Unique<vk::VkDescriptorSet>                   descriptorSet           (createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer()));
2138         const ComputePipeline                                                   pipeline                        (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
2139
2140         const vk::VkMemoryInputFlags                                    inputBit                        = (isUniformBuffer) ? (vk::VK_MEMORY_INPUT_UNIFORM_READ_BIT) : (vk::VK_MEMORY_INPUT_SHADER_READ_BIT);
2141         const vk::VkBufferMemoryBarrier                                 bufferBarrierA          =
2142         {
2143                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2144                 DE_NULL,
2145                 vk::VK_MEMORY_OUTPUT_HOST_WRITE_BIT,            // outputMask
2146                 inputBit,                                                                       // inputMask
2147                 vk::VK_QUEUE_FAMILY_IGNORED,                            // srcQueueFamilyIndex
2148                 vk::VK_QUEUE_FAMILY_IGNORED,                            // destQueueFamilyIndex
2149                 *bufferA,                                                                       // buffer
2150                 (vk::VkDeviceSize)0u,                                           // offset
2151                 (vk::VkDeviceSize)bufferSizeA,                          // size
2152         };
2153         const vk::VkBufferMemoryBarrier                                 bufferBarrierB          =
2154         {
2155                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2156                 DE_NULL,
2157                 vk::VK_MEMORY_OUTPUT_HOST_WRITE_BIT,            // outputMask
2158                 inputBit,                                                                       // inputMask
2159                 vk::VK_QUEUE_FAMILY_IGNORED,                            // srcQueueFamilyIndex
2160                 vk::VK_QUEUE_FAMILY_IGNORED,                            // destQueueFamilyIndex
2161                 *bufferB,                                                                       // buffer
2162                 (vk::VkDeviceSize)0u,                                           // offset
2163                 (vk::VkDeviceSize)bufferSizeB,                          // size
2164         };
2165
2166         const deUint32                                                                  numSrcBuffers           = getInterfaceNumResources(m_shaderInterface);
2167
2168         const vk::VkDescriptorSet                                               descriptorSets[]        = { *descriptorSet };
2169         const int                                                                               numDescriptorSets       = DE_LENGTH_OF_ARRAY(descriptorSets);
2170         const deUint32* const                                                   dynamicOffsets          = (m_setDynamicOffset) ? (bindTimeOffsets) : (DE_NULL);
2171         const deUint32                                                                  numDynamicOffsets       = (m_setDynamicOffset) ? (numSrcBuffers) : (0);
2172         const void* const                                                               preBarriers[]           = { &bufferBarrierA, &bufferBarrierB };
2173         const int                                                                               numPreBarriers          = numSrcBuffers;
2174         const void* const                                                               postBarriers[]          = { m_result.getResultReadBarrier() };
2175         const int                                                                               numPostBarriers         = DE_LENGTH_OF_ARRAY(postBarriers);
2176
2177         const ComputeCommand                                                    compute                         (m_vki,
2178                                                                                                                                                  m_device,
2179                                                                                                                                                  pipeline.getPipeline(),
2180                                                                                                                                                  pipeline.getPipelineLayout(),
2181                                                                                                                                                  tcu::UVec3(4, 1, 1),
2182                                                                                                                                                  numDescriptorSets,     descriptorSets,
2183                                                                                                                                                  numDynamicOffsets,     dynamicOffsets,
2184                                                                                                                                                  numPreBarriers,        preBarriers,
2185                                                                                                                                                  numPostBarriers,       postBarriers);
2186
2187         const tcu::Vec4                                                                 refQuadrantValue14      = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)         ? (colorA2) :
2188                                                                                                                                                   (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS)      ? (colorB2) :
2189                                                                                                                                                   (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)          ? (colorB2) :
2190                                                                                                                                                                                                                                                                         (tcu::Vec4(-2.0f));
2191         const tcu::Vec4                                                                 refQuadrantValue23      = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)         ? (colorA1) :
2192                                                                                                                                                   (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS)      ? (colorA1) :
2193                                                                                                                                                   (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)          ? (colorA1) :
2194                                                                                                                                                                                                                                                                         (tcu::Vec4(-2.0f));
2195         const tcu::Vec4                                                                 references[4]           =
2196         {
2197                 refQuadrantValue14,
2198                 refQuadrantValue23,
2199                 refQuadrantValue23,
2200                 refQuadrantValue14,
2201         };
2202         tcu::Vec4                                                                               results[4];
2203
2204         compute.submitAndWait(m_queueFamilyIndex, m_queue);
2205         m_result.readResultContentsTo(&results);
2206
2207         // verify
2208         if (results[0] == references[0] &&
2209                 results[1] == references[1] &&
2210                 results[2] == references[2] &&
2211                 results[3] == references[3])
2212         {
2213                 return tcu::TestStatus::pass("Pass");
2214         }
2215         else if (results[0] == tcu::Vec4(-1.0f) &&
2216                          results[1] == tcu::Vec4(-1.0f) &&
2217                          results[2] == tcu::Vec4(-1.0f) &&
2218                          results[3] == tcu::Vec4(-1.0f))
2219         {
2220                 m_context.getTestContext().getLog()
2221                         << tcu::TestLog::Message
2222                         << "Result buffer was not written to."
2223                         << tcu::TestLog::EndMessage;
2224                 return tcu::TestStatus::fail("Result buffer was not written to");
2225         }
2226         else
2227         {
2228                 m_context.getTestContext().getLog()
2229                         << tcu::TestLog::Message
2230                         << "Error expected ["
2231                                 << references[0] << ", "
2232                                 << references[1] << ", "
2233                                 << references[2] << ", "
2234                                 << references[3] << "], got ["
2235                                 << results[0] << ", "
2236                                 << results[1] << ", "
2237                                 << results[2] << ", "
2238                                 << results[3] << "]"
2239                         << tcu::TestLog::EndMessage;
2240                 return tcu::TestStatus::fail("Invalid result values");
2241         }
2242 }
2243
2244 class QuadrantRendederCase : public vkt::TestCase
2245 {
2246 public:
2247                                                                         QuadrantRendederCase            (tcu::TestContext&              testCtx,
2248                                                                                                                                  const char*                    name,
2249                                                                                                                                  const char*                    description,
2250                                                                                                                                  glu::GLSLVersion               glslVersion,
2251                                                                                                                                  vk::VkShaderStageFlags exitingStages,
2252                                                                                                                                  vk::VkShaderStageFlags activeStages);
2253 private:
2254         virtual std::string                             genExtensionDeclarations        (vk::VkShaderStage stage) const = 0;
2255         virtual std::string                             genResourceDeclarations         (vk::VkShaderStage stage, int numUsedBindings) const = 0;
2256         virtual std::string                             genResourceAccessSource         (vk::VkShaderStage stage) const = 0;
2257         virtual std::string                             genNoAccessSource                       (void) const = 0;
2258
2259         std::string                                             genVertexSource                         (void) const;
2260         std::string                                             genTessCtrlSource                       (void) const;
2261         std::string                                             genTessEvalSource                       (void) const;
2262         std::string                                             genGeometrySource                       (void) const;
2263         std::string                                             genFragmentSource                       (void) const;
2264         std::string                                             genComputeSource                        (void) const;
2265
2266         void                                                    initPrograms                            (vk::SourceCollections& programCollection) const;
2267
2268 protected:
2269         const glu::GLSLVersion                  m_glslVersion;
2270         const vk::VkShaderStageFlags    m_exitingStages;
2271         const vk::VkShaderStageFlags    m_activeStages;
2272 };
2273
2274 QuadrantRendederCase::QuadrantRendederCase (tcu::TestContext&           testCtx,
2275                                                                                         const char*                             name,
2276                                                                                         const char*                             description,
2277                                                                                         glu::GLSLVersion                glslVersion,
2278                                                                                         vk::VkShaderStageFlags  exitingStages,
2279                                                                                         vk::VkShaderStageFlags  activeStages)
2280         : vkt::TestCase         (testCtx, name, description)
2281         , m_glslVersion         (glslVersion)
2282         , m_exitingStages       (exitingStages)
2283         , m_activeStages        (activeStages)
2284 {
2285         DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages);
2286 }
2287
2288 std::string QuadrantRendederCase::genVertexSource (void) const
2289 {
2290         const char* const       nextStageName   = ((m_exitingStages & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0u)      ? ("tsc")
2291                                                                                 : ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)          ? ("geo")
2292                                                                                 : ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)          ? ("frag")
2293                                                                                 : (DE_NULL);
2294         const char* const       versionDecl             = glu::getGLSLVersionDeclaration(m_glslVersion);
2295         std::ostringstream      buf;
2296
2297         if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
2298         {
2299                 // active vertex shader
2300                 buf << versionDecl << "\n"
2301                         << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX)
2302                         << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX, 0)
2303                         << "layout(location = 0) out highp vec4 " << nextStageName << "_color;\n"
2304                         << "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
2305                         << "void main (void)\n"
2306                         << "{\n"
2307                         << "    highp vec4 result_position;\n"
2308                         << "    highp int quadrant_id;\n"
2309                         << s_quadrantGenVertexPosSource
2310                         << "    gl_Position = result_position;\n"
2311                         << "    " << nextStageName << "_quadrant_id = quadrant_id;\n"
2312                         << "\n"
2313                         << "    highp vec4 result_color;\n"
2314                         << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX)
2315                         << "    " << nextStageName << "_color = result_color;\n"
2316                         << "}\n";
2317         }
2318         else
2319         {
2320                 // do nothing
2321                 buf << versionDecl << "\n"
2322                         << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX)
2323                         << "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n"
2324                         << "void main (void)\n"
2325                         << "{\n"
2326                         << "    highp vec4 result_position;\n"
2327                         << "    highp int quadrant_id;\n"
2328                         << s_quadrantGenVertexPosSource
2329                         << "    gl_Position = result_position;\n"
2330                         << "    " << nextStageName << "_quadrant_id = quadrant_id;\n"
2331                         << "}\n";
2332         }
2333
2334         return buf.str();
2335 }
2336
2337 std::string QuadrantRendederCase::genTessCtrlSource (void) const
2338 {
2339         const char* const       versionDecl             = glu::getGLSLVersionDeclaration(m_glslVersion);
2340         const bool                      extRequired             = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2341         const char* const       tessExtDecl             = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
2342         std::ostringstream      buf;
2343
2344         if ((m_activeStages & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0u)
2345         {
2346                 // contributing not implemented
2347                 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESS_CONTROL_BIT);
2348
2349                 // active tc shader
2350                 buf << versionDecl << "\n"
2351                         << tessExtDecl
2352                         << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESS_CONTROL)
2353                         << "layout(vertices=3) out;\n"
2354                         << genResourceDeclarations(vk::VK_SHADER_STAGE_TESS_CONTROL, 0)
2355                         << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
2356                         << "layout(location = 0) out highp vec4 tes_color[];\n"
2357                         << "void main (void)\n"
2358                         << "{\n"
2359                         << "    highp vec4 result_color;\n"
2360                         << "    highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n"
2361                         << genResourceAccessSource(vk::VK_SHADER_STAGE_TESS_CONTROL)
2362                         << "\n"
2363                         << "    tes_color[gl_InvocationID] = result_color;\n"
2364                         << "\n"
2365                         << "    // no dynamic input block indexing\n"
2366                         << "    highp vec4 position;\n"
2367                         << "    if (gl_InvocationID == 0)\n"
2368                         << "            position = gl_in[0].gl_Position;\n"
2369                         << "    else if (gl_InvocationID == 1)\n"
2370                         << "            position = gl_in[1].gl_Position;\n"
2371                         << "    else\n"
2372                         << "            position = gl_in[2].gl_Position;\n"
2373                         << "    gl_out[gl_InvocationID].gl_Position = position;\n"
2374                         << "    gl_TessLevelInner[0] = 2.8;\n"
2375                         << "    gl_TessLevelInner[1] = 2.8;\n"
2376                         << "    gl_TessLevelOuter[0] = 2.8;\n"
2377                         << "    gl_TessLevelOuter[1] = 2.8;\n"
2378                         << "    gl_TessLevelOuter[2] = 2.8;\n"
2379                         << "    gl_TessLevelOuter[3] = 2.8;\n"
2380                         << "}\n";
2381         }
2382         else if ((m_activeStages & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0u)
2383         {
2384                 // active te shader, tc passthru
2385                 buf << versionDecl << "\n"
2386                         << tessExtDecl
2387                         << "layout(vertices=3) out;\n"
2388                         << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n"
2389                         << "layout(location = 1) flat out highp int tes_quadrant_id[];\n"
2390                         << "void main (void)\n"
2391                         << "{\n"
2392                         << "    tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n"
2393                         << "\n"
2394                         << "    // no dynamic input block indexing\n"
2395                         << "    highp vec4 position;\n"
2396                         << "    if (gl_InvocationID == 0)\n"
2397                         << "            position = gl_in[0].gl_Position;\n"
2398                         << "    else if (gl_InvocationID == 1)\n"
2399                         << "            position = gl_in[1].gl_Position;\n"
2400                         << "    else\n"
2401                         << "            position = gl_in[2].gl_Position;\n"
2402                         << "    gl_out[gl_InvocationID].gl_Position = position;\n"
2403                         << "    gl_TessLevelInner[0] = 2.8;\n"
2404                         << "    gl_TessLevelInner[1] = 2.8;\n"
2405                         << "    gl_TessLevelOuter[0] = 2.8;\n"
2406                         << "    gl_TessLevelOuter[1] = 2.8;\n"
2407                         << "    gl_TessLevelOuter[2] = 2.8;\n"
2408                         << "    gl_TessLevelOuter[3] = 2.8;\n"
2409                         << "}\n";
2410         }
2411         else
2412         {
2413                 // passthrough not implemented
2414                 DE_FATAL("not implemented");
2415         }
2416
2417         return buf.str();
2418 }
2419
2420 std::string QuadrantRendederCase::genTessEvalSource (void) const
2421 {
2422         const char* const       versionDecl             = glu::getGLSLVersionDeclaration(m_glslVersion);
2423         const bool                      extRequired             = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2424         const char* const       tessExtDecl             = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : "";
2425         std::ostringstream      buf;
2426
2427         if ((m_activeStages & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0u)
2428         {
2429                 // contributing not implemented
2430                 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT);
2431
2432                 // active te shader
2433                 buf << versionDecl << "\n"
2434                         << tessExtDecl
2435                         << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESS_EVALUATION)
2436                         << "layout(triangles) in;\n"
2437                         << genResourceDeclarations(vk::VK_SHADER_STAGE_TESS_EVALUATION, 0)
2438                         << "layout(location = 1) flat in highp int tes_quadrant_id[];\n"
2439                         << "layout(location = 0) out highp vec4 frag_color;\n"
2440                         << "void main (void)\n"
2441                         << "{\n"
2442                         << "    highp vec4 result_color;\n"
2443                         << "    highp int quadrant_id = tes_quadrant_id[0];\n"
2444                         << genResourceAccessSource(vk::VK_SHADER_STAGE_TESS_EVALUATION)
2445                         << "\n"
2446                         << "    frag_color = result_color;\n"
2447                         << "    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"
2448                         << "}\n";
2449         }
2450         else if ((m_activeStages & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0u)
2451         {
2452                 // contributing not implemented
2453                 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESS_CONTROL_BIT);
2454
2455                 // active tc shader, te is passthru
2456                 buf << versionDecl << "\n"
2457                         << tessExtDecl
2458                         << "layout(triangles) in;\n"
2459                         << "layout(location = 0) in highp vec4 tes_color[];\n"
2460                         << "layout(location = 0) out highp vec4 frag_color;\n"
2461                         << "void main (void)\n"
2462                         << "{\n"
2463                         << "    frag_color = tes_color[0];\n"
2464                         << "    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"
2465                         << "}\n";
2466         }
2467         else
2468         {
2469                 // passthrough not implemented
2470                 DE_FATAL("not implemented");
2471         }
2472
2473         return buf.str();
2474 }
2475
2476 std::string QuadrantRendederCase::genGeometrySource (void) const
2477 {
2478         const char* const       versionDecl             = glu::getGLSLVersionDeclaration(m_glslVersion);
2479         const bool                      extRequired             = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES;
2480         const char* const       geomExtDecl             = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : "";
2481         std::ostringstream      buf;
2482
2483         if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
2484         {
2485                 // contributing not implemented
2486                 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT);
2487
2488                 // active geometry shader
2489                 buf << versionDecl << "\n"
2490                         << geomExtDecl
2491                         << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY)
2492                         << "layout(triangles) in;\n"
2493                         << "layout(triangle_strip, max_vertices=4) out;\n"
2494                         << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY, 0)
2495                         << "layout(location = 1) flat in highp int geo_quadrant_id[];\n"
2496                         << "layout(location = 0) out highp vec4 frag_color;\n"
2497                         << "void main (void)\n"
2498                         << "{\n"
2499                         << "    highp int quadrant_id;\n"
2500                         << "    highp vec4 result_color;\n"
2501                         << "\n"
2502                         << "    quadrant_id = geo_quadrant_id[0];\n"
2503                         << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY)
2504                         << "    frag_color = result_color;\n"
2505                         << "    gl_Position = gl_in[0].gl_Position;\n"
2506                         << "    EmitVertex();\n"
2507                         << "\n"
2508                         << "    quadrant_id = geo_quadrant_id[1];\n"
2509                         << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY)
2510                         << "    frag_color = result_color;\n"
2511                         << "    gl_Position = gl_in[1].gl_Position;\n"
2512                         << "    EmitVertex();\n"
2513                         << "\n"
2514                         << "    quadrant_id = geo_quadrant_id[2];\n"
2515                         << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY)
2516                         << "    frag_color = result_color;\n"
2517                         << "    gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n"
2518                         << "    EmitVertex();\n"
2519                         << "\n"
2520                         << "    quadrant_id = geo_quadrant_id[0];\n"
2521                         << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY)
2522                         << "    frag_color = result_color;\n"
2523                         << "    gl_Position = gl_in[2].gl_Position;\n"
2524                         << "    EmitVertex();\n"
2525                         << "}\n";
2526         }
2527         else
2528         {
2529                 // passthrough not implemented
2530                 DE_FATAL("not implemented");
2531         }
2532
2533         return buf.str();
2534 }
2535
2536 std::string QuadrantRendederCase::genFragmentSource (void) const
2537 {
2538         const char* const       versionDecl             = glu::getGLSLVersionDeclaration(m_glslVersion);
2539         std::ostringstream      buf;
2540
2541         if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
2542         {
2543                 buf << versionDecl << "\n"
2544                         << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY)
2545                         << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT, 0);
2546
2547                 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
2548                 {
2549                         // there are other stages, this is just a contributor
2550                         buf << "layout(location = 0) in mediump vec4 frag_color;\n";
2551                 }
2552
2553                 buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
2554                         << "layout(location = 0) out mediump vec4 o_color;\n"
2555                         << "void main (void)\n"
2556                         << "{\n"
2557                         << "    highp int quadrant_id = frag_quadrant_id;\n"
2558                         << "    highp vec4 result_color;\n"
2559                         << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT);
2560
2561                 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT)
2562                 {
2563                         // just contributor
2564                         buf     << "    if (frag_quadrant_id < 2)\n"
2565                                 << "            o_color = result_color;\n"
2566                                 << "    else\n"
2567                                 << "            o_color = frag_color;\n";
2568                 }
2569                 else
2570                         buf << "        o_color = result_color;\n";
2571
2572                 buf << "}\n";
2573         }
2574         else if (m_activeStages == 0u)
2575         {
2576                 // special case, no active stages
2577                 buf << versionDecl << "\n"
2578                         << "layout(location = 1) flat in highp int frag_quadrant_id;\n"
2579                         << "layout(location = 0) out mediump vec4 o_color;\n"
2580                         << "void main (void)\n"
2581                         << "{\n"
2582                         << "    highp int quadrant_id = frag_quadrant_id;\n"
2583                         << "    highp vec4 result_color;\n"
2584                         << genNoAccessSource()
2585                         << "    o_color = result_color;\n"
2586                         << "}\n";
2587         }
2588         else
2589         {
2590                 // passthrough
2591                 buf <<  versionDecl << "\n"
2592                         <<      "layout(location = 0) in mediump vec4 frag_color;\n"
2593                                 "layout(location = 0) out mediump vec4 o_color;\n"
2594                                 "void main (void)\n"
2595                                 "{\n"
2596                                 "       o_color = frag_color;\n"
2597                                 "}\n";
2598         }
2599
2600         return buf.str();
2601 }
2602
2603 std::string QuadrantRendederCase::genComputeSource (void) const
2604 {
2605         const char* const       versionDecl             = glu::getGLSLVersionDeclaration(m_glslVersion);
2606         std::ostringstream      buf;
2607
2608         buf     << versionDecl << "\n"
2609                 << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE)
2610                 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2611                 << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE, 1)
2612                 << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
2613                 << "{\n"
2614                 << "    highp vec4 read_colors[4];\n"
2615                 << "} b_out;\n"
2616                 << "void main(void)\n"
2617                 << "{\n"
2618                 << "    highp int quadrant_id = int(gl_WorkGroupID.x);\n"
2619                 << "    highp vec4 result_color;\n"
2620                 << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE)
2621                 << "    b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
2622                 << "}\n";
2623
2624         return buf.str();
2625 }
2626
2627 void QuadrantRendederCase::initPrograms (vk::SourceCollections& programCollection) const
2628 {
2629         if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u)
2630                 programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource());
2631
2632         if ((m_exitingStages & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0u)
2633                 programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource());
2634
2635         if ((m_exitingStages & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0u)
2636                 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource());
2637
2638         if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u)
2639                 programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource());
2640
2641         if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u)
2642                 programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource());
2643
2644         if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u)
2645                 programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource());
2646 }
2647
2648 class BufferDescriptorCase : public QuadrantRendederCase
2649 {
2650 public:
2651         enum
2652         {
2653                 FLAG_VIEW_OFFSET                        = (1u << 1u),
2654                 FLAG_DYNAMIC_OFFSET_ZERO        = (1u << 2u),
2655                 FLAG_DYNAMIC_OFFSET_NONZERO     = (1u << 3u),
2656         };
2657         // enum continues where resource flags ends
2658         DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
2659
2660                                                                         BufferDescriptorCase            (tcu::TestContext&              testCtx,
2661                                                                                                                                  const char*                    name,
2662                                                                                                                                  const char*                    description,
2663                                                                                                                                  bool                                   isPrimaryCmdBuf,
2664                                                                                                                                  vk::VkDescriptorType   descriptorType,
2665                                                                                                                                  vk::VkShaderStageFlags exitingStages,
2666                                                                                                                                  vk::VkShaderStageFlags activeStages,
2667                                                                                                                                  ShaderInputInterface   shaderInterface,
2668                                                                                                                                  deUint32                               flags);
2669
2670 private:
2671         std::string                                             genExtensionDeclarations        (vk::VkShaderStage stage) const;
2672         std::string                                             genResourceDeclarations         (vk::VkShaderStage stage, int numUsedBindings) const;
2673         std::string                                             genResourceAccessSource         (vk::VkShaderStage stage) const;
2674         std::string                                             genNoAccessSource                       (void) const;
2675
2676         vkt::TestInstance*                              createInstance                          (vkt::Context& context) const;
2677
2678         const bool                                              m_viewOffset;
2679         const bool                                              m_dynamicOffsetSet;
2680         const bool                                              m_dynamicOffsetNonZero;
2681         const bool                                              m_isPrimaryCmdBuf;
2682         const vk::VkDescriptorType              m_descriptorType;
2683         const ShaderInputInterface              m_shaderInterface;
2684 };
2685
2686 BufferDescriptorCase::BufferDescriptorCase (tcu::TestContext&           testCtx,
2687                                                                                         const char*                             name,
2688                                                                                         const char*                             description,
2689                                                                                         bool                                    isPrimaryCmdBuf,
2690                                                                                         vk::VkDescriptorType    descriptorType,
2691                                                                                         vk::VkShaderStageFlags  exitingStages,
2692                                                                                         vk::VkShaderStageFlags  activeStages,
2693                                                                                         ShaderInputInterface    shaderInterface,
2694                                                                                         deUint32                                flags)
2695         : QuadrantRendederCase          (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
2696         , m_viewOffset                          ((flags & FLAG_VIEW_OFFSET) != 0u)
2697         , m_dynamicOffsetSet            ((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u)
2698         , m_dynamicOffsetNonZero        ((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u)
2699         , m_isPrimaryCmdBuf                     (isPrimaryCmdBuf)
2700         , m_descriptorType                      (descriptorType)
2701         , m_shaderInterface                     (shaderInterface)
2702 {
2703 }
2704
2705 std::string BufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStage stage) const
2706 {
2707         DE_UNREF(stage);
2708         return "";
2709 }
2710
2711 std::string BufferDescriptorCase::genResourceDeclarations (vk::VkShaderStage stage, int numUsedBindings) const
2712 {
2713         DE_UNREF(stage);
2714
2715         const bool                      isUniform               = isUniformDescriptorType(m_descriptorType);
2716         const char* const       storageType             = (isUniform) ? ("uniform") : ("buffer");
2717         std::ostringstream      buf;
2718
2719         switch (m_shaderInterface)
2720         {
2721                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2722                         buf     << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
2723                                 << "{\n"
2724                                 << "    highp vec4 colorA;\n"
2725                                 << "    highp vec4 colorB;\n"
2726                                 << "} b_instance;\n";
2727                         break;
2728
2729                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
2730                         buf     << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferNameA\n"
2731                                 << "{\n"
2732                                 << "    highp vec4 colorA;\n"
2733                                 << "    highp vec4 colorB;\n"
2734                                 << "} b_instanceA;\n"
2735                                 << "layout(set = 0, binding = " << (numUsedBindings+1) << ", std140) " << storageType << " BufferNameB\n"
2736                                 << "{\n"
2737                                 << "    highp vec4 colorA;\n"
2738                                 << "    highp vec4 colorB;\n"
2739                                 << "} b_instanceB;\n";
2740                         break;
2741
2742                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2743                         buf     << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n"
2744                                 << "{\n"
2745                                 << "    highp vec4 colorA;\n"
2746                                 << "    highp vec4 colorB;\n"
2747                                 << "} b_instances[2];\n";
2748                         break;
2749
2750                 default:
2751                         DE_FATAL("Impossible");
2752         }
2753
2754         return buf.str();
2755 }
2756
2757 std::string BufferDescriptorCase::genResourceAccessSource (vk::VkShaderStage stage) const
2758 {
2759         DE_UNREF(stage);
2760
2761         std::ostringstream buf;
2762
2763         switch (m_shaderInterface)
2764         {
2765                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
2766                         buf << "        if (quadrant_id == 1 || quadrant_id == 2)\n"
2767                                 << "            result_color = b_instance.colorA;\n"
2768                                 << "    else\n"
2769                                 << "            result_color = b_instance.colorB;\n";
2770                         break;
2771
2772                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
2773                         buf << "        if (quadrant_id == 1 || quadrant_id == 2)\n"
2774                                 << "            result_color = b_instanceA.colorA;\n"
2775                                 << "    else\n"
2776                                 << "            result_color = b_instanceB.colorB;\n";
2777                         break;
2778
2779                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
2780                         buf << "        if (quadrant_id == 1 || quadrant_id == 2)\n"
2781                                 << "            result_color = b_instances[0].colorA;\n"
2782                                 << "    else\n"
2783                                 << "            result_color = b_instances[1].colorB;\n";
2784                         break;
2785
2786                 default:
2787                         DE_FATAL("Impossible");
2788         }
2789
2790         return buf.str();
2791 }
2792
2793 std::string BufferDescriptorCase::genNoAccessSource (void) const
2794 {
2795         return "        if (quadrant_id == 1 || quadrant_id == 2)\n"
2796                    "            result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
2797                    "    else\n"
2798                    "            result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
2799 }
2800
2801 vkt::TestInstance* BufferDescriptorCase::createInstance (vkt::Context& context) const
2802 {
2803         if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
2804         {
2805                 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
2806                 return new BufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
2807         }
2808         else
2809                 return new BufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero);
2810 }
2811
2812 class ImageInstanceImages
2813 {
2814 public:
2815                                                                                 ImageInstanceImages             (const vk::DeviceInterface&             vki,
2816                                                                                                                                  vk::VkDevice                                   device,
2817                                                                                                                                  deUint32                                               queueFamilyIndex,
2818                                                                                                                                  vk::VkQueue                                    queue,
2819                                                                                                                                  vk::Allocator&                                 allocator,
2820                                                                                                                                  vk::VkDescriptorType                   descriptorType,
2821                                                                                                                                  vk::VkImageViewType                    viewType,
2822                                                                                                                                  int                                                    numImages,
2823                                                                                                                                  deUint32                                               baseMipLevel,
2824                                                                                                                                  deUint32                                               baseArraySlice);
2825
2826 private:
2827         static vk::Move<vk::VkImage>            createImage                             (const vk::DeviceInterface&                     vki,
2828                                                                                                                                  vk::VkDevice                                           device,
2829                                                                                                                                  vk::Allocator&                                         allocator,
2830                                                                                                                                  vk::VkDescriptorType                           descriptorType,
2831                                                                                                                                  vk::VkImageViewType                            viewType,
2832                                                                                                                                  const tcu::TextureLevelPyramid&        sourceImage,
2833                                                                                                                                  de::MovePtr<vk::Allocation>*           outAllocation);
2834
2835         static vk::Move<vk::VkImageView>        createImageView                 (const vk::DeviceInterface&                     vki,
2836                                                                                                                                  vk::VkDevice                                           device,
2837                                                                                                                                  vk::VkImageViewType                            viewType,
2838                                                                                                                                  const tcu::TextureLevelPyramid&        sourceImage,
2839                                                                                                                                  vk::VkImage                                            image,
2840                                                                                                                                  deUint32                                                       baseMipLevel,
2841                                                                                                                                  deUint32                                                       baseArraySlice);
2842
2843         void                                                            populateSourceImage             (tcu::TextureLevelPyramid*                      dst,
2844                                                                                                                                  bool                                                           isFirst) const;
2845
2846         void                                                            uploadImage                             (const vk::DeviceInterface&                     vki,
2847                                                                                                                                  vk::VkDevice                                           device,
2848                                                                                                                                  deUint32                                                       queueFamilyIndex,
2849                                                                                                                                  vk::VkQueue                                            queue,
2850                                                                                                                                  vk::Allocator&                                         allocator,
2851                                                                                                                                  vk::VkImage                                            image,
2852                                                                                                                                  const tcu::TextureLevelPyramid&        data);
2853
2854 protected:
2855         enum
2856         {
2857                 IMAGE_SIZE              = 64,
2858                 NUM_MIP_LEVELS  = 2,
2859                 ARRAY_SIZE              = 2,
2860         };
2861
2862         const vk::VkImageViewType                       m_viewType;
2863         const deUint32                                          m_baseMipLevel;
2864         const deUint32                                          m_baseArraySlice;
2865
2866         const tcu::TextureFormat                        m_imageFormat;
2867         tcu::TextureLevelPyramid                        m_sourceImageA;
2868         tcu::TextureLevelPyramid                        m_sourceImageB;
2869
2870         de::MovePtr<vk::Allocation>                     m_imageMemoryA;
2871         de::MovePtr<vk::Allocation>                     m_imageMemoryB;
2872         vk::Move<vk::VkImage>                           m_imageA;
2873         vk::Move<vk::VkImage>                           m_imageB;
2874         vk::Move<vk::VkImageView>                       m_imageViewA;
2875         vk::Move<vk::VkImageView>                       m_imageViewB;
2876 };
2877
2878 ImageInstanceImages::ImageInstanceImages (const vk::DeviceInterface&    vki,
2879                                                                                   vk::VkDevice                                  device,
2880                                                                                   deUint32                                              queueFamilyIndex,
2881                                                                                   vk::VkQueue                                   queue,
2882                                                                                   vk::Allocator&                                allocator,
2883                                                                                   vk::VkDescriptorType                  descriptorType,
2884                                                                                   vk::VkImageViewType                   viewType,
2885                                                                                   int                                                   numImages,
2886                                                                                   deUint32                                              baseMipLevel,
2887                                                                                   deUint32                                              baseArraySlice)
2888         : m_viewType            (viewType)
2889         , m_baseMipLevel        (baseMipLevel)
2890         , m_baseArraySlice      (baseArraySlice)
2891         , m_imageFormat         (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
2892         , m_sourceImageA        (m_imageFormat, NUM_MIP_LEVELS)
2893         , m_sourceImageB        (m_imageFormat, NUM_MIP_LEVELS)
2894         , m_imageMemoryA        (DE_NULL)
2895         , m_imageMemoryB        (DE_NULL)
2896         , m_imageA                      (vk::Move<vk::VkImage>())
2897         , m_imageB                      (vk::Move<vk::VkImage>())
2898         , m_imageViewA          (vk::Move<vk::VkImageView>())
2899         , m_imageViewB          (vk::Move<vk::VkImageView>())
2900 {
2901         DE_ASSERT(numImages == 1 || numImages == 2);
2902
2903         populateSourceImage(&m_sourceImageA, true);
2904         m_imageA = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageA, &m_imageMemoryA);
2905         m_imageViewA = createImageView(vki, device, viewType, m_sourceImageA, *m_imageA, m_baseMipLevel, m_baseArraySlice);
2906         uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageA, m_sourceImageA);
2907
2908         if (numImages == 2)
2909         {
2910                 populateSourceImage(&m_sourceImageB, false);
2911                 m_imageB = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageB, &m_imageMemoryB);
2912                 m_imageViewB = createImageView(vki, device, viewType, m_sourceImageB, *m_imageB, m_baseMipLevel, m_baseArraySlice);
2913                 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageB, m_sourceImageB);
2914         }
2915 }
2916
2917 vk::Move<vk::VkImage> ImageInstanceImages::createImage (const vk::DeviceInterface&                      vki,
2918                                                                                                                 vk::VkDevice                                            device,
2919                                                                                                                 vk::Allocator&                                          allocator,
2920                                                                                                                 vk::VkDescriptorType                            descriptorType,
2921                                                                                                                 vk::VkImageViewType                                     viewType,
2922                                                                                                                 const tcu::TextureLevelPyramid&         sourceImage,
2923                                                                                                                 de::MovePtr<vk::Allocation>*            outAllocation)
2924 {
2925         const tcu::ConstPixelBufferAccess       baseLevel       = sourceImage.getLevel(0);
2926         const bool                                                      isCube          = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
2927         const bool                                                      isStorage       = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
2928         const deUint32                                          readUsage       = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT);
2929         const deUint32                                          arraySize       = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)                ? (baseLevel.getHeight())
2930                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)                ? (baseLevel.getDepth())
2931                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                                                                               ? (1)
2932                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)    ? (baseLevel.getDepth()) // cube: numFaces * numLayers
2933                                                                                                                                                                                                                                                                                                         : (0);
2934         const vk::VkExtent3D                            extent          =
2935         {
2936                 // x
2937                 (deInt32)baseLevel.getWidth(),
2938
2939                 // y
2940                 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (deInt32)baseLevel.getHeight(),
2941
2942                 // z
2943                 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((deInt32)baseLevel.getDepth()) : (1),
2944         };
2945         const vk::VkImageCreateInfo                     createInfo      =
2946         {
2947                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2948                 DE_NULL,
2949                 viewTypeToImageType(viewType),                                                                                  // imageType
2950                 mapToVkTextureFormat(baseLevel.getFormat()),                                                    // format
2951                 extent,                                                                                                                                 // extent
2952                 (deUint32)sourceImage.getNumLevels(),                                                                   // mipLevels
2953                 arraySize,                                                                                                                              // arraySize
2954                 1,                                                                                                                                              // samples
2955                 vk::VK_IMAGE_TILING_OPTIMAL,                                                                                    // tiling
2956                 readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT,                                // usage
2957                 isCube ? ((deUint32)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) : (0u),    // flags
2958                 vk::VK_SHARING_MODE_EXCLUSIVE,                                                                                  // sharingMode
2959                 0u,                                                                                                                                             // queueFamilyCount
2960                 DE_NULL,                                                                                                                                // pQueueFamilyIndices
2961                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                                                                                  // initialLayout
2962         };
2963         vk::Move<vk::VkImage>                           image           (vk::createImage(vki, device, &createInfo));
2964
2965         *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any);
2966         return image;
2967 }
2968
2969 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView (const vk::DeviceInterface&                      vki,
2970                                                                                                                                 vk::VkDevice                                            device,
2971                                                                                                                                 vk::VkImageViewType                                     viewType,
2972                                                                                                                                 const tcu::TextureLevelPyramid&         sourceImage,
2973                                                                                                                                 vk::VkImage                                                     image,
2974                                                                                                                                 deUint32                                                        baseMipLevel,
2975                                                                                                                                 deUint32                                                        baseArraySlice)
2976 {
2977         const tcu::ConstPixelBufferAccess       baseLevel                       = sourceImage.getLevel(0);
2978         const deUint32                                          viewTypeBaseSlice       = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * baseArraySlice) : (baseArraySlice);
2979         const deUint32                                          viewArraySize           = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D)                       ? (1)
2980                                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)         ? (baseLevel.getHeight() - viewTypeBaseSlice)
2981                                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D)                       ? (1)
2982                                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)         ? (baseLevel.getDepth() - viewTypeBaseSlice)
2983                                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                       ? (1)
2984                                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE)                     ? (6)
2985                                                                                                                         : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)       ? (baseLevel.getDepth() - viewTypeBaseSlice) // cube: numFaces * numLayers
2986                                                                                                                                                                                                                                 : (0);
2987
2988         DE_ASSERT(viewArraySize > 0);
2989
2990         const vk::VkImageSubresourceRange       resourceRange   =
2991         {
2992                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
2993                 baseMipLevel,                                                                   // baseMipLevel
2994                 sourceImage.getNumLevels() - baseMipLevel,              // mipLevels
2995                 viewTypeBaseSlice,                                                              // baseArraySlice
2996                 viewArraySize,                                                                  // arraySize
2997         };
2998         const vk::VkImageViewCreateInfo         createInfo              =
2999         {
3000                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
3001                 DE_NULL,
3002                 image,                                                                                  // image
3003                 viewType,                                                                               // viewType
3004                 mapToVkTextureFormat(baseLevel.getFormat()),    // format
3005                 {
3006                         vk::VK_CHANNEL_SWIZZLE_R,
3007                         vk::VK_CHANNEL_SWIZZLE_G,
3008                         vk::VK_CHANNEL_SWIZZLE_B,
3009                         vk::VK_CHANNEL_SWIZZLE_A
3010                 },                                                                                              // channels
3011                 resourceRange,                                                                  // subresourceRange
3012                 0u,                                                                                             // flags
3013         };
3014         return vk::createImageView(vki, device, &createInfo);
3015 }
3016
3017 void ImageInstanceImages::populateSourceImage (tcu::TextureLevelPyramid* dst, bool isFirst) const
3018 {
3019         const int numLevels = dst->getNumLevels();
3020
3021         for (int level = 0; level < numLevels; ++level)
3022         {
3023                 const int       width   = IMAGE_SIZE >> level;
3024                 const int       height  = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)            ? (ARRAY_SIZE)
3025                                                                                                                                                                                                                                                                 : (IMAGE_SIZE >> level);
3026                 const int       depth   = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)            ? (1)
3027                                                         : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)            ? (ARRAY_SIZE)
3028                                                         : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)        ? (6 * ARRAY_SIZE)
3029                                                         : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                                                                                     ? (IMAGE_SIZE >> level)
3030                                                                                                                                                                                                                                                                 : (1);
3031
3032                 dst->allocLevel(level, width, height, depth);
3033
3034                 {
3035                         const tcu::PixelBufferAccess levelAccess = dst->getLevel(level);
3036
3037                         for (int z = 0; z < depth; ++z)
3038                         for (int y = 0; y < height; ++y)
3039                         for (int x = 0; x < width; ++x)
3040                         {
3041                                 const int                       gradPos = x + y + z;
3042                                 const int                       gradMax = width + height + depth - 3;
3043
3044                                 const int                       red             = 255 * gradPos / gradMax;                                                                                                      //!< gradient from 0 -> max (detects large offset errors)
3045                                 const int                       green   = ((gradPos % 2 == 0) ? (127) : (0)) + ((gradPos % 4 < 3) ? (128) : (0));       //!< 3-level M pattern (detects small offset errors)
3046                                 const int                       blue    = (128 * level / numLevels) + (isFirst ? 127 : 0);                                                      //!< level and image index (detects incorrect lod / image)
3047
3048                                 DE_ASSERT(de::inRange(red, 0, 255));
3049                                 DE_ASSERT(de::inRange(green, 0, 255));
3050                                 DE_ASSERT(de::inRange(blue, 0, 255));
3051
3052                                 levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z);
3053                         }
3054                 }
3055         }
3056 }
3057
3058 void ImageInstanceImages::uploadImage (const vk::DeviceInterface&               vki,
3059                                                                            vk::VkDevice                                         device,
3060                                                                            deUint32                                                     queueFamilyIndex,
3061                                                                            vk::VkQueue                                          queue,
3062                                                                            vk::Allocator&                                       allocator,
3063                                                                            vk::VkImage                                          image,
3064                                                                            const tcu::TextureLevelPyramid&      data)
3065 {
3066         const deUint32                                          arraySize                                       = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) :
3067                                                                                                                                           (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * (deUint32)ARRAY_SIZE) :
3068                                                                                                                                           ((deUint32)ARRAY_SIZE);
3069         const deUint32                                          dataBufferSize                          = getTextureLevelPyramidDataSize(data);
3070         const vk::VkBufferCreateInfo            bufferCreateInfo                        =
3071         {
3072                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
3073                 DE_NULL,
3074                 dataBufferSize,                                                                         // size
3075                 vk::VK_BUFFER_USAGE_TRANSFER_SOURCE_BIT,                        // usage
3076                 0u,                                                                                                     // flags
3077                 vk::VK_SHARING_MODE_EXCLUSIVE,                                          // sharingMode
3078                 0u,                                                                                                     // queueFamilyCount
3079                 DE_NULL,                                                                                        // pQueueFamilyIndices
3080         };
3081         const vk::Unique<vk::VkBuffer>          dataBuffer                                      (vk::createBuffer(vki, device, &bufferCreateInfo));
3082         const de::MovePtr<vk::Allocation>       dataBufferMemory                        = allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible);
3083         const vk::VkFenceCreateInfo                     fenceCreateInfo                         =
3084         {
3085                 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
3086                 DE_NULL,
3087                 0u,                                                                                                     // flags
3088         };
3089         const vk::VkBufferMemoryBarrier         preMemoryBarrier                        =
3090         {
3091                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
3092                 DE_NULL,
3093                 vk::VK_MEMORY_OUTPUT_HOST_WRITE_BIT,                            // outputMask
3094                 vk::VK_MEMORY_INPUT_TRANSFER_BIT,                                       // inputMask
3095                 vk::VK_QUEUE_FAMILY_IGNORED,                                            // srcQueueFamilyIndex
3096                 vk::VK_QUEUE_FAMILY_IGNORED,                                            // destQueueFamilyIndex
3097                 *dataBuffer,                                                                            // buffer
3098                 0u,                                                                                                     // offset
3099                 dataBufferSize,                                                                         // size
3100         };
3101         const vk::VkImageSubresourceRange       fullSubrange                            =
3102         {
3103                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                          // aspectMask
3104                 0u,                                                                                                     // baseMipLevel
3105                 (deUint32)data.getNumLevels(),                                          // mipLevels
3106                 0u,                                                                                                     // baseArraySlice
3107                 arraySize,                                                                                      // arraySize
3108         };
3109         const vk::VkImageMemoryBarrier          preImageBarrier                         =
3110         {
3111                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3112                 DE_NULL,
3113                 0u,                                                                                                     // outputMask
3114                 0u,                                                                                                     // inputMask
3115                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                                          // oldLayout
3116                 vk::VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,       // newLayout
3117                 vk::VK_QUEUE_FAMILY_IGNORED,                                            // srcQueueFamilyIndex
3118                 vk::VK_QUEUE_FAMILY_IGNORED,                                            // destQueueFamilyIndex
3119                 image,                                                                                          // image
3120                 fullSubrange                                                                            // subresourceRange
3121         };
3122         const vk::VkImageMemoryBarrier          postImageBarrier                        =
3123         {
3124                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3125                 DE_NULL,
3126                 vk::VK_MEMORY_OUTPUT_TRANSFER_BIT,                                      // outputMask
3127                 vk::VK_MEMORY_INPUT_SHADER_READ_BIT,                            // inputMask
3128                 vk::VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL,       // oldLayout
3129                 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,           // newLayout
3130                 vk::VK_QUEUE_FAMILY_IGNORED,                                            // srcQueueFamilyIndex
3131                 vk::VK_QUEUE_FAMILY_IGNORED,                                            // destQueueFamilyIndex
3132                 image,                                                                                          // image
3133                 fullSubrange                                                                            // subresourceRange
3134         };
3135         const vk::VkCmdPoolCreateInfo           cmdPoolCreateInfo                       =
3136         {
3137                 vk::VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,
3138                 DE_NULL,
3139                 queueFamilyIndex,                                                                       // queueFamilyIndex
3140                 vk::VK_CMD_POOL_CREATE_TRANSIENT_BIT,                           // flags
3141         };
3142         const vk::Unique<vk::VkCmdPool>         cmdPool                                         (vk::createCommandPool(vki, device, &cmdPoolCreateInfo));
3143         const vk::VkCmdBufferCreateInfo         cmdBufCreateInfo                        =
3144         {
3145                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
3146                 DE_NULL,
3147                 *cmdPool,                                                                                       // cmdPool
3148                 vk::VK_CMD_BUFFER_LEVEL_PRIMARY,                                        // level
3149                 0u,                                                                                                     // flags
3150         };
3151         const vk::VkCmdBufferBeginInfo          cmdBufBeginInfo                         =
3152         {
3153                 vk::VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
3154                 DE_NULL,
3155                 vk::VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | vk::VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,    // flags
3156                 (vk::VkRenderPass)0u,                                                                                                                                                   // renderPass
3157                 0u,                                                                                                                                                                                             // subpass
3158                 (vk::VkFramebuffer)0u,                                                                                                                                                  // framebuffer
3159         };
3160
3161         const vk::Unique<vk::VkCmdBuffer>       cmd                                                     (vk::createCommandBuffer(vki, device, &cmdBufCreateInfo));
3162         const void* const                                       preBarriers[2]                          = { &preMemoryBarrier, &preImageBarrier };
3163         const void* const                                       postBarriers[1]                         = { &postImageBarrier };
3164         const vk::Unique<vk::VkFence>           cmdCompleteFence                        (vk::createFence(vki, device, &fenceCreateInfo));
3165         const deUint64                                          infiniteTimeout                         = ~(deUint64)0u;
3166         std::vector<vk::VkBufferImageCopy>      copySlices;
3167
3168         // copy data to buffer
3169         writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, m_viewType , &copySlices);
3170         flushMappedMemoryRange(vki, device, dataBufferMemory->getMemory(), dataBufferMemory->getOffset(), dataBufferSize);
3171
3172         // record command buffer
3173         VK_CHECK(vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
3174         vki.cmdPipelineBarrier(*cmd, 0u, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_FALSE, DE_LENGTH_OF_ARRAY(preBarriers), preBarriers);
3175         vki.cmdCopyBufferToImage(*cmd, *dataBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DESTINATION_OPTIMAL, (deUint32)copySlices.size(), &copySlices[0]);
3176         vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_FALSE, DE_LENGTH_OF_ARRAY(postBarriers), postBarriers);
3177         VK_CHECK(vki.endCommandBuffer(*cmd));
3178
3179         // submit and wait for command buffer to complete before killing it
3180         VK_CHECK(vki.queueSubmit(queue, 1, &cmd.get(), *cmdCompleteFence));
3181         VK_CHECK(vki.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
3182 }
3183
3184 class ImageFetchInstanceImages : private ImageInstanceImages
3185 {
3186 public:
3187                                                                 ImageFetchInstanceImages        (const vk::DeviceInterface&             vki,
3188                                                                                                                          vk::VkDevice                                   device,
3189                                                                                                                          deUint32                                               queueFamilyIndex,
3190                                                                                                                          vk::VkQueue                                    queue,
3191                                                                                                                          vk::Allocator&                                 allocator,
3192                                                                                                                          vk::VkDescriptorType                   descriptorType,
3193                                                                                                                          ShaderInputInterface                   shaderInterface,
3194                                                                                                                          vk::VkImageViewType                    viewType,
3195                                                                                                                          deUint32                                               baseMipLevel,
3196                                                                                                                          deUint32                                               baseArraySlice);
3197
3198         static tcu::IVec3                       getFetchPos                                     (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx);
3199         tcu::Vec4                                       fetchImageValue                         (int fetchPosNdx) const;
3200
3201         inline vk::VkImageView          getImageViewA                           (void) const { return *m_imageViewA; }
3202         inline vk::VkImageView          getImageViewB                           (void) const { return *m_imageViewB; }
3203
3204 private:
3205         enum
3206         {
3207                 // some arbitrary sample points for all four quadrants
3208                 SAMPLE_POINT_0_X = 6,
3209                 SAMPLE_POINT_0_Y = 13,
3210                 SAMPLE_POINT_0_Z = 49,
3211
3212                 SAMPLE_POINT_1_X = 51,
3213                 SAMPLE_POINT_1_Y = 40,
3214                 SAMPLE_POINT_1_Z = 44,
3215
3216                 SAMPLE_POINT_2_X = 42,
3217                 SAMPLE_POINT_2_Y = 26,
3218                 SAMPLE_POINT_2_Z = 19,
3219
3220                 SAMPLE_POINT_3_X = 25,
3221                 SAMPLE_POINT_3_Y = 25,
3222                 SAMPLE_POINT_3_Z = 18,
3223         };
3224
3225         const ShaderInputInterface      m_shaderInterface;
3226 };
3227
3228 ImageFetchInstanceImages::ImageFetchInstanceImages (const vk::DeviceInterface&  vki,
3229                                                                                                         vk::VkDevice                            device,
3230                                                                                                         deUint32                                        queueFamilyIndex,
3231                                                                                                         vk::VkQueue                                     queue,
3232                                                                                                         vk::Allocator&                          allocator,
3233                                                                                                         vk::VkDescriptorType            descriptorType,
3234                                                                                                         ShaderInputInterface            shaderInterface,
3235                                                                                                         vk::VkImageViewType                     viewType,
3236                                                                                                         deUint32                                        baseMipLevel,
3237                                                                                                         deUint32                                        baseArraySlice)
3238         : ImageInstanceImages   (vki,
3239                                                          device,
3240                                                          queueFamilyIndex,
3241                                                          queue,
3242                                                          allocator,
3243                                                          descriptorType,
3244                                                          viewType,
3245                                                          getInterfaceNumResources(shaderInterface),     // numImages
3246                                                          baseMipLevel,
3247                                                          baseArraySlice)
3248         , m_shaderInterface             (shaderInterface)
3249 {
3250 }
3251
3252 bool isImageViewTypeArray (vk::VkImageViewType type)
3253 {
3254         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;
3255 }
3256
3257 tcu::IVec3 ImageFetchInstanceImages::getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx)
3258 {
3259         const tcu::IVec3        fetchPositions[4]       =
3260         {
3261                 tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z),
3262                 tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z),
3263                 tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z),
3264                 tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z),
3265         };
3266         const tcu::IVec3        coord                           = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
3267         const deUint32          imageSize                       = (deUint32)IMAGE_SIZE >> baseMipLevel;
3268         const deUint32          arraySize                       = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
3269
3270         switch (viewType)
3271         {
3272                 case vk::VK_IMAGE_VIEW_TYPE_1D:
3273                 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:   return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0);
3274                 case vk::VK_IMAGE_VIEW_TYPE_2D:
3275                 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:   return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize);
3276                 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
3277                 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6));
3278                 case vk::VK_IMAGE_VIEW_TYPE_3D:                 return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize);
3279                 default:
3280                         DE_FATAL("Impossible");
3281                         return tcu::IVec3();
3282         }
3283 }
3284
3285 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue (int fetchPosNdx) const
3286 {
3287         DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4));
3288
3289         const tcu::TextureLevelPyramid& fetchSrcA       = m_sourceImageA;
3290         const tcu::TextureLevelPyramid& fetchSrcB       = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
3291         const tcu::TextureLevelPyramid& fetchSrc        = ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB
3292         const tcu::IVec3                                fetchPos        = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
3293
3294         return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z());
3295 }
3296
3297 class ImageFetchRenderInstance : public SingleCmdRenderInstance
3298 {
3299 public:
3300                                                                                                         ImageFetchRenderInstance        (vkt::Context&                  context,
3301                                                                                                                                                                  bool                                   isPrimaryCmdBuf,
3302                                                                                                                                                                  vk::VkDescriptorType   descriptorType,
3303                                                                                                                                                                  vk::VkShaderStageFlags stageFlags,
3304                                                                                                                                                                  ShaderInputInterface   shaderInterface,
3305                                                                                                                                                                  vk::VkImageViewType    viewType,
3306                                                                                                                                                                  deUint32                               baseMipLevel,
3307                                                                                                                                                                  deUint32                               baseArraySlice);
3308
3309 private:
3310         static vk::Move<vk::VkDescriptorSetLayout>              createDescriptorSetLayout       (const vk::DeviceInterface&     vki,
3311                                                                                                                                                                  vk::VkDevice                           device,
3312                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
3313                                                                                                                                                                  ShaderInputInterface           shaderInterface,
3314                                                                                                                                                                  vk::VkShaderStageFlags         stageFlags);
3315
3316         static vk::Move<vk::VkPipelineLayout>                   createPipelineLayout            (const vk::DeviceInterface&     vki,
3317                                                                                                                                                                  vk::VkDevice                           device,
3318                                                                                                                                                                  vk::VkDescriptorSetLayout      descriptorSetLayout);
3319
3320         static vk::Move<vk::VkDescriptorPool>                   createDescriptorPool            (const vk::DeviceInterface&     vki,
3321                                                                                                                                                                  vk::VkDevice                           device,
3322                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
3323                                                                                                                                                                  ShaderInputInterface           shaderInterface);
3324
3325         static vk::Move<vk::VkDescriptorSet>                    createDescriptorSet                     (const vk::DeviceInterface&     vki,
3326                                                                                                                                                                  vk::VkDevice                           device,
3327                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
3328                                                                                                                                                                  ShaderInputInterface           shaderInterface,
3329                                                                                                                                                                  vk::VkDescriptorSetLayout      layout,
3330                                                                                                                                                                  vk::VkDescriptorPool           pool,
3331                                                                                                                                                                  vk::VkImageView                        viewA,
3332                                                                                                                                                                  vk::VkImageView                        viewB);
3333
3334         void                                                                                    logTestPlan                                     (void) const;
3335         vk::VkPipelineLayout                                                    getPipelineLayout                       (void) const;
3336         void                                                                                    writeDrawCmdBuffer                      (vk::VkCmdBuffer cmd) const;
3337         tcu::TestStatus                                                                 verifyResultImage                       (const tcu::ConstPixelBufferAccess& result) const;
3338
3339         enum
3340         {
3341                 RENDER_SIZE = 128,
3342         };
3343
3344         const vk::VkDescriptorType                                              m_descriptorType;
3345         const vk::VkShaderStageFlags                                    m_stageFlags;
3346         const ShaderInputInterface                                              m_shaderInterface;
3347         const vk::VkImageViewType                                               m_viewType;
3348         const deUint32                                                                  m_baseMipLevel;
3349         const deUint32                                                                  m_baseArraySlice;
3350
3351         const vk::Unique<vk::VkDescriptorSetLayout>             m_descriptorSetLayout;
3352         const vk::Unique<vk::VkPipelineLayout>                  m_pipelineLayout;
3353         const ImageFetchInstanceImages                                  m_images;
3354         const vk::Unique<vk::VkDescriptorPool>                  m_descriptorPool;
3355         const vk::Unique<vk::VkDescriptorSet>                   m_descriptorSet;
3356 };
3357
3358 ImageFetchRenderInstance::ImageFetchRenderInstance      (vkt::Context&                  context,
3359                                                                                                          bool                                   isPrimaryCmdBuf,
3360                                                                                                          vk::VkDescriptorType   descriptorType,
3361                                                                                                          vk::VkShaderStageFlags stageFlags,
3362                                                                                                          ShaderInputInterface   shaderInterface,
3363                                                                                                          vk::VkImageViewType    viewType,
3364                                                                                                          deUint32                               baseMipLevel,
3365                                                                                                          deUint32                               baseArraySlice)
3366         : SingleCmdRenderInstance       (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
3367         , m_descriptorType                      (descriptorType)
3368         , m_stageFlags                          (stageFlags)
3369         , m_shaderInterface                     (shaderInterface)
3370         , m_viewType                            (viewType)
3371         , m_baseMipLevel                        (baseMipLevel)
3372         , m_baseArraySlice                      (baseArraySlice)
3373         , m_descriptorSetLayout         (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
3374         , m_pipelineLayout                      (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
3375         , m_images                                      (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
3376         , m_descriptorPool                      (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
3377         , m_descriptorSet                       (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_images.getImageViewA(), m_images.getImageViewB()))
3378 {
3379 }
3380
3381 vk::Move<vk::VkDescriptorSetLayout> ImageFetchRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&             vki,
3382                                                                                                                                                                                  vk::VkDevice                                   device,
3383                                                                                                                                                                                  vk::VkDescriptorType                   descriptorType,
3384                                                                                                                                                                                  ShaderInputInterface                   shaderInterface,
3385                                                                                                                                                                                  vk::VkShaderStageFlags                 stageFlags)
3386 {
3387         vk::DescriptorSetLayoutBuilder builder;
3388
3389         switch (shaderInterface)
3390         {
3391                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3392                         builder.addSingleBinding(descriptorType, stageFlags);
3393                         break;
3394
3395                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
3396                         builder.addSingleBinding(descriptorType, stageFlags);
3397                         builder.addSingleBinding(descriptorType, stageFlags);
3398                         break;
3399
3400                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3401                         builder.addArrayBinding(descriptorType, 2u, stageFlags);
3402                         break;
3403
3404                 default:
3405                         DE_FATAL("Impossible");
3406         }
3407
3408         return builder.build(vki, device);
3409 }
3410
3411 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout (const vk::DeviceInterface&       vki,
3412                                                                                                                                                            vk::VkDevice                                 device,
3413                                                                                                                                                            vk::VkDescriptorSetLayout    descriptorSetLayout)
3414 {
3415         const vk::VkPipelineLayoutCreateInfo createInfo =
3416         {
3417                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
3418                 DE_NULL,
3419                 1,                                              // descriptorSetCount
3420                 &descriptorSetLayout,   // pSetLayouts
3421                 0u,                                             // pushConstantRangeCount
3422                 DE_NULL,                                // pPushConstantRanges
3423         };
3424         return vk::createPipelineLayout(vki, device, &createInfo);
3425 }
3426
3427 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool (const vk::DeviceInterface&       vki,
3428                                                                                                                                                            vk::VkDevice                                 device,
3429                                                                                                                                                            vk::VkDescriptorType                 descriptorType,
3430                                                                                                                                                            ShaderInputInterface                 shaderInterface)
3431 {
3432         return vk::DescriptorPoolBuilder()
3433                 .addType(descriptorType, getInterfaceNumResources(shaderInterface))
3434                 .build(vki, device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
3435 }
3436
3437 vk::Move<vk::VkDescriptorSet> ImageFetchRenderInstance::createDescriptorSet (const vk::DeviceInterface&         vki,
3438                                                                                                                                                          vk::VkDevice                                   device,
3439                                                                                                                                                          vk::VkDescriptorType                   descriptorType,
3440                                                                                                                                                          ShaderInputInterface                   shaderInterface,
3441                                                                                                                                                          vk::VkDescriptorSetLayout              layout,
3442                                                                                                                                                          vk::VkDescriptorPool                   pool,
3443                                                                                                                                                          vk::VkImageView                                viewA,
3444                                                                                                                                                          vk::VkImageView                                viewB)
3445 {
3446         const vk::VkDescriptorInfo              imageInfos[2]   =
3447         {
3448                 createDescriptorInfo(viewA, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
3449                 createDescriptorInfo(viewB, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
3450         };
3451
3452         vk::Move<vk::VkDescriptorSet>   descriptorSet   = allocDescriptorSet(vki, device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
3453         vk::DescriptorSetUpdateBuilder  builder;
3454
3455         switch (shaderInterface)
3456         {
3457                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3458                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
3459                         break;
3460
3461                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
3462                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]);
3463                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &imageInfos[1]);
3464                         break;
3465
3466                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3467                         builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, imageInfos);
3468                         break;
3469
3470                 default:
3471                         DE_FATAL("Impossible");
3472         }
3473
3474         builder.update(vki, device);
3475         return descriptorSet;
3476 }
3477
3478 void ImageFetchRenderInstance::logTestPlan (void) const
3479 {
3480         std::ostringstream msg;
3481
3482         msg << "Rendering 2x2 grid.\n"
3483                 << "Single descriptor set. Descriptor set contains "
3484                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
3485                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
3486                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
3487                             (const char*)DE_NULL)
3488                 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
3489                 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
3490
3491         if (m_baseMipLevel)
3492                 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
3493         if (m_baseArraySlice)
3494                 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
3495
3496         if (m_stageFlags == 0u)
3497         {
3498                 msg << "Descriptors are not accessed in any shader stage.\n";
3499         }
3500         else
3501         {
3502                 msg << "Color in each cell is fetched using the descriptor(s):\n";
3503
3504                 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3505                 {
3506                         msg << "Test sample " << resultNdx << ": fetching at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
3507
3508                         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
3509                         {
3510                                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
3511                                 msg << " from descriptor " << srcResourceNdx;
3512                         }
3513
3514                         msg << "\n";
3515                 }
3516
3517                 msg << "Descriptors are accessed in {"
3518                         << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)                      ? (" vertex")                   : (""))
3519                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0)        ? (" tess_control")             : (""))
3520                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0)     ? (" tess_evaluation")  : (""))
3521                         << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)            ? (" geometry")                 : (""))
3522                         << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)            ? (" fragment")                 : (""))
3523                         << " } stages.";
3524         }
3525
3526         m_context.getTestContext().getLog()
3527                 << tcu::TestLog::Message
3528                 << msg.str()
3529                 << tcu::TestLog::EndMessage;
3530 }
3531
3532 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout (void) const
3533 {
3534         return *m_pipelineLayout;
3535 }
3536
3537 void ImageFetchRenderInstance::writeDrawCmdBuffer (vk::VkCmdBuffer cmd) const
3538 {
3539         m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
3540         m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
3541 }
3542
3543 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
3544 {
3545         const tcu::Vec4         green           (0.0f, 1.0f, 0.0f, 1.0f);
3546         const tcu::Vec4         yellow          (1.0f, 1.0f, 0.0f, 1.0f);
3547         const bool                      doFetch         = (m_stageFlags != 0u); // no active stages? Then don't fetch
3548         const tcu::Vec4         sample0         = (!doFetch) ? (yellow) : (m_images.fetchImageValue(0));
3549         const tcu::Vec4         sample1         = (!doFetch) ? (green)  : (m_images.fetchImageValue(1));
3550         const tcu::Vec4         sample2         = (!doFetch) ? (green)  : (m_images.fetchImageValue(2));
3551         const tcu::Vec4         sample3         = (!doFetch) ? (yellow) : (m_images.fetchImageValue(3));
3552         tcu::Surface            reference       (m_targetSize.x(), m_targetSize.y());
3553
3554         drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
3555
3556         if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
3557                 return tcu::TestStatus::fail("Image verification failed");
3558         else
3559                 return tcu::TestStatus::pass("Pass");
3560 }
3561
3562 class ImageFetchComputeInstance : public vkt::TestInstance
3563 {
3564 public:
3565                                                                                         ImageFetchComputeInstance       (vkt::Context&                  context,
3566                                                                                                                                                  vk::VkDescriptorType   descriptorType,
3567                                                                                                                                                  ShaderInputInterface   shaderInterface,
3568                                                                                                                                                  vk::VkImageViewType    viewType,
3569                                                                                                                                                  deUint32                               baseMipLevel,
3570                                                                                                                                                  deUint32                               baseArraySlice);
3571
3572 private:
3573         vk::Move<vk::VkDescriptorSetLayout>             createDescriptorSetLayout       (void) const;
3574         vk::Move<vk::VkDescriptorPool>                  createDescriptorPool            (void) const;
3575         vk::Move<vk::VkDescriptorSet>                   createDescriptorSet                     (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
3576
3577         tcu::TestStatus                                                 iterate                                         (void);
3578         void                                                                    logTestPlan                                     (void) const;
3579         tcu::TestStatus                                                 testResourceAccess                      (void);
3580
3581         const vk::VkDescriptorType                              m_descriptorType;
3582         const ShaderInputInterface                              m_shaderInterface;
3583         const vk::VkImageViewType                               m_viewType;
3584         const deUint32                                                  m_baseMipLevel;
3585         const deUint32                                                  m_baseArraySlice;
3586
3587         const vk::DeviceInterface&                              m_vki;
3588         const vk::VkDevice                                              m_device;
3589         const vk::VkQueue                                               m_queue;
3590         const deUint32                                                  m_queueFamilyIndex;
3591         vk::Allocator&                                                  m_allocator;
3592
3593         const ComputeInstanceResultBuffer               m_result;
3594         const ImageFetchInstanceImages                  m_images;
3595 };
3596
3597 ImageFetchComputeInstance::ImageFetchComputeInstance (Context&                          context,
3598                                                                                                           vk::VkDescriptorType  descriptorType,
3599                                                                                                           ShaderInputInterface  shaderInterface,
3600                                                                                                           vk::VkImageViewType   viewType,
3601                                                                                                           deUint32                              baseMipLevel,
3602                                                                                                           deUint32                              baseArraySlice)
3603         : vkt::TestInstance             (context)
3604         , m_descriptorType              (descriptorType)
3605         , m_shaderInterface             (shaderInterface)
3606         , m_viewType                    (viewType)
3607         , m_baseMipLevel                (baseMipLevel)
3608         , m_baseArraySlice              (baseArraySlice)
3609         , m_vki                                 (context.getDeviceInterface())
3610         , m_device                              (context.getDevice())
3611         , m_queue                               (context.getUniversalQueue())
3612         , m_queueFamilyIndex    (context.getUniversalQueueFamilyIndex())
3613         , m_allocator                   (context.getDefaultAllocator())
3614         , m_result                              (m_vki, m_device, m_allocator)
3615         , m_images                              (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice)
3616 {
3617 }
3618
3619 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout (void) const
3620 {
3621         vk::DescriptorSetLayoutBuilder builder;
3622
3623         builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3624
3625         switch (m_shaderInterface)
3626         {
3627                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3628                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3629                         break;
3630
3631                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
3632                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3633                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3634                         break;
3635
3636                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3637                         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
3638                         break;
3639
3640                 default:
3641                         DE_FATAL("Impossible");
3642         };
3643
3644         return builder.build(m_vki, m_device);
3645 }
3646
3647 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool (void) const
3648 {
3649         return vk::DescriptorPoolBuilder()
3650                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
3651                 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
3652                 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
3653 }
3654
3655 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
3656 {
3657         const vk::VkDescriptorInfo              resultInfo              = createDescriptorInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
3658         const vk::VkDescriptorInfo              imageInfos[2]   =
3659         {
3660                 createDescriptorInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
3661                 createDescriptorInfo(m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
3662         };
3663
3664         vk::Move<vk::VkDescriptorSet>   descriptorSet   = allocDescriptorSet(m_vki, m_device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
3665         vk::DescriptorSetUpdateBuilder  builder;
3666
3667         // result
3668         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
3669
3670         // images
3671         switch (m_shaderInterface)
3672         {
3673                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
3674                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
3675                         break;
3676
3677                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
3678                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]);
3679                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &imageInfos[1]);
3680                         break;
3681
3682                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
3683                         builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, imageInfos);
3684                         break;
3685
3686                 default:
3687                         DE_FATAL("Impossible");
3688         }
3689
3690         builder.update(m_vki, m_device);
3691         return descriptorSet;
3692 }
3693
3694 tcu::TestStatus ImageFetchComputeInstance::iterate (void)
3695 {
3696         logTestPlan();
3697         return testResourceAccess();
3698 }
3699
3700 void ImageFetchComputeInstance::logTestPlan (void) const
3701 {
3702         std::ostringstream msg;
3703
3704         msg << "Fetching 4 values from image in compute shader.\n"
3705                 << "Single descriptor set. Descriptor set contains "
3706                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
3707                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
3708                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
3709                             (const char*)DE_NULL)
3710                 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
3711                 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
3712
3713         if (m_baseMipLevel)
3714                 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
3715         if (m_baseArraySlice)
3716                 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
3717
3718         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3719         {
3720                 msg << "Test sample " << resultNdx << ": fetch at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
3721
3722                 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
3723                 {
3724                         const int srcResourceNdx = (resultNdx % 2); // ABAB source
3725                         msg << " from descriptor " << srcResourceNdx;
3726                 }
3727
3728                 msg << "\n";
3729         }
3730
3731         m_context.getTestContext().getLog()
3732                 << tcu::TestLog::Message
3733                 << msg.str()
3734                 << tcu::TestLog::EndMessage;
3735 }
3736
3737 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess (void)
3738 {
3739         const vk::Unique<vk::VkDescriptorSetLayout>             descriptorSetLayout     (createDescriptorSetLayout());
3740         const vk::Unique<vk::VkDescriptorPool>                  descriptorPool          (createDescriptorPool());
3741         const vk::Unique<vk::VkDescriptorSet>                   descriptorSet           (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
3742         const ComputePipeline                                                   pipeline                        (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
3743
3744         const vk::VkDescriptorSet                                               descriptorSets[]        = { *descriptorSet };
3745         const int                                                                               numDescriptorSets       = DE_LENGTH_OF_ARRAY(descriptorSets);
3746         const deUint32* const                                                   dynamicOffsets          = DE_NULL;
3747         const int                                                                               numDynamicOffsets       = 0;
3748         const void*     const*                                                          preBarriers                     = DE_NULL;
3749         const int                                                                               numPreBarriers          = 0;
3750         const void* const                                                               postBarriers[]          = { m_result.getResultReadBarrier() };
3751         const int                                                                               numPostBarriers         = DE_LENGTH_OF_ARRAY(postBarriers);
3752
3753         const ComputeCommand                                                    compute                         (m_vki,
3754                                                                                                                                                  m_device,
3755                                                                                                                                                  pipeline.getPipeline(),
3756                                                                                                                                                  pipeline.getPipelineLayout(),
3757                                                                                                                                                  tcu::UVec3(4, 1, 1),
3758                                                                                                                                                  numDescriptorSets,     descriptorSets,
3759                                                                                                                                                  numDynamicOffsets,     dynamicOffsets,
3760                                                                                                                                                  numPreBarriers,        preBarriers,
3761                                                                                                                                                  numPostBarriers,       postBarriers);
3762
3763         tcu::Vec4                                                                               results[4];
3764         bool                                                                                    anyResultSet            = false;
3765         bool                                                                                    allResultsOk            = true;
3766
3767         compute.submitAndWait(m_queueFamilyIndex, m_queue);
3768         m_result.readResultContentsTo(&results);
3769
3770         // verify
3771         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
3772         {
3773                 const tcu::Vec4 result                          = results[resultNdx];
3774                 const tcu::Vec4 reference                       = m_images.fetchImageValue(resultNdx);
3775                 const tcu::Vec4 conversionThreshold     = tcu::Vec4(1.0f / 255.0f);
3776
3777                 if (result != tcu::Vec4(-1.0f))
3778                         anyResultSet = true;
3779
3780                 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
3781                 {
3782                         allResultsOk = false;
3783
3784                         m_context.getTestContext().getLog()
3785                                 << tcu::TestLog::Message
3786                                 << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
3787                                 << tcu::TestLog::EndMessage;
3788                 }
3789         }
3790
3791         // read back and verify
3792         if (allResultsOk)
3793                 return tcu::TestStatus::pass("Pass");
3794         else if (anyResultSet)
3795                 return tcu::TestStatus::fail("Invalid result values");
3796         else
3797         {
3798                 m_context.getTestContext().getLog()
3799                         << tcu::TestLog::Message
3800                         << "Result buffer was not written to."
3801                         << tcu::TestLog::EndMessage;
3802                 return tcu::TestStatus::fail("Result buffer was not written to");
3803         }
3804 }
3805
3806 class ImageSampleInstanceImages : private ImageInstanceImages
3807 {
3808 public:
3809                                                                                 ImageSampleInstanceImages       (const vk::DeviceInterface&             vki,
3810                                                                                                                                          vk::VkDevice                                   device,
3811                                                                                                                                          deUint32                                               queueFamilyIndex,
3812                                                                                                                                          vk::VkQueue                                    queue,
3813                                                                                                                                          vk::Allocator&                                 allocator,
3814                                                                                                                                          vk::VkDescriptorType                   descriptorType,
3815                                                                                                                                          ShaderInputInterface                   shaderInterface,
3816                                                                                                                                          vk::VkImageViewType                    viewType,
3817                                                                                                                                          deUint32                                               baseMipLevel,
3818                                                                                                                                          deUint32                                               baseArraySlice,
3819                                                                                                                                          bool                                                   immutable);
3820
3821         static tcu::Vec4                                        getSamplePos                            (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx);
3822         tcu::Vec4                                                       fetchSampleValue                        (int samplePosNdx) const;
3823
3824         inline vk::VkImageView                          getImageViewA                           (void) const { return *m_imageViewA;    }
3825         inline vk::VkImageView                          getImageViewB                           (void) const { return *m_imageViewB;    }
3826         inline vk::VkSampler                            getSamplerA                                     (void) const { return *m_samplerA;              }
3827         inline vk::VkSampler                            getSamplerB                                     (void) const { return *m_samplerB;              }
3828         inline bool                                                     isImmutable                                     (void) const { return m_isImmutable;    }
3829
3830 private:
3831         static int                                                      getNumImages                            (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface);
3832         static tcu::Sampler                                     createRefSampler                        (bool isFirst);
3833         static vk::Move<vk::VkSampler>          createSampler                           (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format);
3834
3835         static tcu::Texture1DArrayView          getRef1DView                            (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3836         static tcu::Texture2DArrayView          getRef2DView                            (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3837         static tcu::Texture3DView                       getRef3DView                            (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3838         static tcu::TextureCubeArrayView        getRefCubeView                          (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage);
3839
3840         const vk::VkDescriptorType                      m_descriptorType;
3841         const ShaderInputInterface                      m_shaderInterface;
3842         const bool                                                      m_isImmutable;
3843
3844         const tcu::Sampler                                      m_refSamplerA;
3845         const tcu::Sampler                                      m_refSamplerB;
3846         const vk::Unique<vk::VkSampler>         m_samplerA;
3847         const vk::Unique<vk::VkSampler>         m_samplerB;
3848 };
3849
3850 ImageSampleInstanceImages::ImageSampleInstanceImages (const vk::DeviceInterface&        vki,
3851                                                                                                           vk::VkDevice                                  device,
3852                                                                                                           deUint32                                              queueFamilyIndex,
3853                                                                                                           vk::VkQueue                                   queue,
3854                                                                                                           vk::Allocator&                                allocator,
3855                                                                                                           vk::VkDescriptorType                  descriptorType,
3856                                                                                                           ShaderInputInterface                  shaderInterface,
3857                                                                                                           vk::VkImageViewType                   viewType,
3858                                                                                                           deUint32                                              baseMipLevel,
3859                                                                                                           deUint32                                              baseArraySlice,
3860                                                                                                           bool                                                  immutable)
3861         : ImageInstanceImages   (vki,
3862                                                          device,
3863                                                          queueFamilyIndex,
3864                                                          queue,
3865                                                          allocator,
3866                                                          descriptorType,
3867                                                          viewType,
3868                                                          getNumImages(descriptorType, shaderInterface),
3869                                                          baseMipLevel,
3870                                                          baseArraySlice)
3871         , m_descriptorType              (descriptorType)
3872         , m_shaderInterface             (shaderInterface)
3873         , m_isImmutable                 (immutable)
3874         , m_refSamplerA                 (createRefSampler(true))
3875         , m_refSamplerB                 (createRefSampler(false))
3876         , m_samplerA                    (createSampler(vki, device, m_refSamplerA, m_imageFormat))
3877         , m_samplerB                    ((getInterfaceNumResources(m_shaderInterface) == 1u)
3878                                                                 ? vk::Move<vk::VkSampler>()
3879                                                                 : createSampler(vki, device, m_refSamplerB, m_imageFormat))
3880 {
3881 }
3882
3883 tcu::Vec4 ImageSampleInstanceImages::getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx)
3884 {
3885         DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
3886
3887         const deUint32  imageSize       = (deUint32)IMAGE_SIZE >> baseMipLevel;
3888         const deUint32  arraySize       = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1;
3889
3890         // choose arbitrary values that are not ambiguous with NEAREST filtering
3891
3892         switch (viewType)
3893         {
3894                 case vk::VK_IMAGE_VIEW_TYPE_1D:
3895                 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
3896                 case vk::VK_IMAGE_VIEW_TYPE_2D:
3897                 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
3898                 case vk::VK_IMAGE_VIEW_TYPE_3D:
3899                 {
3900                         const tcu::Vec3 coords[4]       =
3901                         {
3902                                 tcu::Vec3(0.75f,
3903                                                   0.5f,
3904                                                   (float)(12u % imageSize) + 0.25f),
3905
3906                                 tcu::Vec3((float)(23u % imageSize) + 0.25f,
3907                                                   (float)(73u % imageSize) + 0.5f,
3908                                                   (float)(16u % imageSize) + 0.5f + (float)imageSize),
3909
3910                                 tcu::Vec3(-(float)(43u % imageSize) + 0.25f,
3911                                                   (float)(84u % imageSize) + 0.5f + (float)imageSize,
3912                                                   (float)(117u % imageSize) + 0.75f),
3913
3914                                 tcu::Vec3((float)imageSize + 0.5f,
3915                                                   (float)(75u % imageSize) + 0.25f,
3916                                                   (float)(83u % imageSize) + 0.25f + (float)imageSize),
3917                         };
3918                         const deUint32  slices[4]       =
3919                         {
3920                                 0u % arraySize,
3921                                 4u % arraySize,
3922                                 9u % arraySize,
3923                                 2u % arraySize,
3924                         };
3925
3926                         if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
3927                                 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3928                                                                  (float)slices[samplePosNdx],
3929                                                                  0.0f,
3930                                                                  0.0f);
3931                         else if (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)
3932                                 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3933                                                                  coords[samplePosNdx].y() / (float)imageSize,
3934                                                                  (float)slices[samplePosNdx],
3935                                                                  0.0f);
3936                         else if (viewType == vk::VK_IMAGE_VIEW_TYPE_3D)
3937                                 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize,
3938                                                                  coords[samplePosNdx].y() / (float)imageSize,
3939                                                                  coords[samplePosNdx].z() / (float)imageSize,
3940                                                                  0.0f);
3941                         else
3942                         {
3943                                 DE_FATAL("Impossible");
3944                                 return tcu::Vec4();
3945                         }
3946                 }
3947
3948                 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
3949                 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
3950                 {
3951                         // \note these values are in [0, texSize]*3 space for convenience
3952                         const tcu::Vec3 coords[4]       =
3953                         {
3954                                 tcu::Vec3(0.75f,
3955                                                   0.5f,
3956                                                   (float)imageSize),
3957
3958                                 tcu::Vec3((float)(13u % imageSize) + 0.25f,
3959                                                   0.0f,
3960                                                   (float)(16u % imageSize) + 0.5f),
3961
3962                                 tcu::Vec3(0.0f,
3963                                                   (float)(84u % imageSize) + 0.5f,
3964                                                   (float)(10u % imageSize) + 0.75f),
3965
3966                                 tcu::Vec3((float)imageSize,
3967                                                   (float)(75u % imageSize) + 0.25f,
3968                                                   (float)(83u % imageSize) + 0.75f),
3969                         };
3970                         const deUint32  slices[4]       =
3971                         {
3972                                 1u % arraySize,
3973                                 2u % arraySize,
3974                                 9u % arraySize,
3975                                 5u % arraySize,
3976                         };
3977
3978                         DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize));
3979                         DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize));
3980                         DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize));
3981
3982                         // map to [-1, 1]*3 space
3983                         return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f,
3984                                                          coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f,
3985                                                          coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f,
3986                                                          (float)slices[samplePosNdx]);
3987                 }
3988
3989                 default:
3990                         DE_FATAL("Impossible");
3991                         return tcu::Vec4();
3992         }
3993 }
3994
3995 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue (int samplePosNdx) const
3996 {
3997         DE_ASSERT(de::inBounds(samplePosNdx, 0, 4));
3998
3999         // texture order is ABAB
4000         const bool                                                                      isSamplerCase   = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER);
4001         const tcu::TextureLevelPyramid&                         sampleSrcA              = m_sourceImageA;
4002         const tcu::TextureLevelPyramid&                         sampleSrcB              = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB);
4003         const tcu::TextureLevelPyramid&                         sampleSrc               = (isSamplerCase) ? (sampleSrcA) : ((samplePosNdx % 2) == 0) ? (sampleSrcA) : (sampleSrcB);
4004
4005         // sampler order is ABAB
4006         const tcu::Sampler&                                                     samplerA                = m_refSamplerA;
4007         const tcu::Sampler&                                                     samplerB                = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_refSamplerA) : (m_refSamplerB);
4008         const tcu::Sampler&                                                     sampler                 = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB);
4009
4010         const tcu::Vec4                                                         samplePos               = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
4011         const float                                                                     lod                             = 0.0f;
4012         std::vector<tcu::ConstPixelBufferAccess>        levelStorage;
4013
4014         switch (m_viewType)
4015         {
4016                 case vk::VK_IMAGE_VIEW_TYPE_1D:
4017                 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:   return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), lod);
4018                 case vk::VK_IMAGE_VIEW_TYPE_2D:
4019                 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);
4020                 case vk::VK_IMAGE_VIEW_TYPE_3D:                 return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod);
4021                 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
4022                 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);
4023
4024                 default:
4025                 {
4026                         DE_FATAL("Impossible");
4027                         return tcu::Vec4();
4028                 }
4029         }
4030 }
4031
4032 int ImageSampleInstanceImages::getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface)
4033 {
4034         // If we are testing separate samplers, just one image is enough
4035         if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4036                 return 1;
4037         else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4038         {
4039                 // combined: numImages == numSamplers
4040                 return getInterfaceNumResources(shaderInterface);
4041         }
4042         else
4043         {
4044                 DE_FATAL("Impossible");
4045                 return 0;
4046         }
4047 }
4048
4049 tcu::Sampler ImageSampleInstanceImages::createRefSampler (bool isFirst)
4050 {
4051         if (isFirst)
4052         {
4053                 // linear, wrapping
4054                 return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
4055         }
4056         else
4057         {
4058                 // nearest, clamping
4059                 return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
4060         }
4061 }
4062
4063 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format)
4064 {
4065         const bool                                              compareEnabled  = (sampler.compare != tcu::Sampler::COMPAREMODE_NONE);
4066         const vk::VkCompareOp                   compareOp               = (compareEnabled) ? (mapToVkCompareOp(sampler.compare)) : (vk::VK_COMPARE_OP_ALWAYS);
4067         const tcu::TextureChannelClass  channelClass    = tcu::getTextureChannelClass(format.type);
4068         const bool                                              isIntTexture    = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
4069         const vk::VkBorderColor                 borderColor             = (isIntTexture) ? (vk::VK_BORDER_COLOR_INT_OPAQUE_WHITE) : (vk::VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE);
4070         const vk::VkSamplerCreateInfo   createInfo              =
4071         {
4072                 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
4073                 DE_NULL,
4074                 mapMagFilterToVkTexFilter(sampler.magFilter),                                                                   // magFilter
4075                 mapMinFilterToVkTexFilter(sampler.minFilter),                                                                   // minFilter
4076                 mapMinFilterToVkTexMipmapMode(sampler.minFilter),                                                               // mipMode
4077                 mapToVkTexAddressMode(sampler.wrapS),                                                                                   // addressU
4078                 mapToVkTexAddressMode(sampler.wrapT),                                                                                   // addressV
4079                 mapToVkTexAddressMode(sampler.wrapR),                                                                                   // addressW
4080                 0.0f,                                                                                                                                                   // mipLodBias
4081                 1,                                                                                                                                                              // maxAnisotropy
4082                 (compareEnabled) ? (vk::VkBool32)(vk::VK_TRUE) : (vk::VkBool32)(vk::VK_FALSE),  // compareEnable
4083                 compareOp,                                                                                                                                              // compareOp
4084                 0.0f,                                                                                                                                                   // minLod
4085                 0.0f,                                                                                                                                                   // maxLod
4086                 borderColor,                                                                                                                                    // borderColor
4087                 vk::VK_FALSE,                                                                                                                                   // unnormalizedCoords
4088         };
4089         return vk::createSampler(vki, device, &createInfo);
4090 }
4091
4092 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4093 {
4094         DE_ASSERT(levelStorage->empty());
4095
4096         const deUint32 numSlices = (deUint32)source.getLevel(0).getHeight();
4097         const deUint32 numLevels = (deUint32)source.getNumLevels();
4098
4099         // cut pyramid from baseMipLevel
4100         for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4101         {
4102                 // cut levels from baseArraySlice
4103                 const tcu::ConstPixelBufferAccess wholeLevel    = source.getLevel(level);
4104                 const tcu::ConstPixelBufferAccess cutLevel              = tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice);
4105                 levelStorage->push_back(cutLevel);
4106         }
4107
4108         return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front());
4109 }
4110
4111 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4112 {
4113         DE_ASSERT(levelStorage->empty());
4114
4115         const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth();
4116         const deUint32 numLevels = (deUint32)source.getNumLevels();
4117
4118         // cut pyramid from baseMipLevel
4119         for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4120         {
4121                 // cut levels from baseArraySlice
4122                 const tcu::ConstPixelBufferAccess wholeLevel    = source.getLevel(level);
4123                 const tcu::ConstPixelBufferAccess cutLevel              = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(), numSlices - baseArraySlice);
4124                 levelStorage->push_back(cutLevel);
4125         }
4126
4127         return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front());
4128 }
4129
4130 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4131 {
4132         DE_ASSERT(levelStorage->empty());
4133         DE_ASSERT(baseArraySlice == 0);
4134         DE_UNREF(baseArraySlice);
4135
4136         const deUint32 numLevels = (deUint32)source.getNumLevels();
4137
4138         // cut pyramid from baseMipLevel
4139         for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4140                 levelStorage->push_back(source.getLevel(level));
4141
4142         return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front());
4143 }
4144
4145 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage)
4146 {
4147         DE_ASSERT(levelStorage->empty());
4148
4149         const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth() / 6;
4150         const deUint32 numLevels = (deUint32)source.getNumLevels();
4151
4152         // cut pyramid from baseMipLevel
4153         for (deUint32 level = baseMipLevel; level < numLevels; ++level)
4154         {
4155                 // cut levels from baseArraySlice
4156                 const tcu::ConstPixelBufferAccess wholeLevel    = source.getLevel(level);
4157                 const tcu::ConstPixelBufferAccess cutLevel              = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(), (numSlices - baseArraySlice) * 6);
4158                 levelStorage->push_back(cutLevel);
4159         }
4160
4161         return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front());
4162 }
4163
4164 class ImageSampleRenderInstance : public SingleCmdRenderInstance
4165 {
4166 public:
4167                                                                                                         ImageSampleRenderInstance               (vkt::Context&                  context,
4168                                                                                                                                                                          bool                                   isPrimaryCmdBuf,
4169                                                                                                                                                                          vk::VkDescriptorType   descriptorType,
4170                                                                                                                                                                          vk::VkShaderStageFlags stageFlags,
4171                                                                                                                                                                          ShaderInputInterface   shaderInterface,
4172                                                                                                                                                                          vk::VkImageViewType    viewType,
4173                                                                                                                                                                          deUint32                               baseMipLevel,
4174                                                                                                                                                                          deUint32                               baseArraySlice,
4175                                                                                                                                                                          bool                                   isImmutable);
4176
4177 private:
4178         static vk::Move<vk::VkDescriptorSetLayout>              createDescriptorSetLayout               (const vk::DeviceInterface&                     vki,
4179                                                                                                                                                                          vk::VkDevice                                           device,
4180                                                                                                                                                                          vk::VkDescriptorType                           descriptorType,
4181                                                                                                                                                                          ShaderInputInterface                           shaderInterface,
4182                                                                                                                                                                          vk::VkShaderStageFlags                         stageFlags,
4183                                                                                                                                                                          const ImageSampleInstanceImages&       images);
4184
4185         static vk::Move<vk::VkPipelineLayout>                   createPipelineLayout                    (const vk::DeviceInterface&     vki,
4186                                                                                                                                                                          vk::VkDevice                           device,
4187                                                                                                                                                                          vk::VkDescriptorSetLayout      descriptorSetLayout);
4188
4189         static vk::Move<vk::VkDescriptorPool>                   createDescriptorPool                    (const vk::DeviceInterface&     vki,
4190                                                                                                                                                                          vk::VkDevice                           device,
4191                                                                                                                                                                          vk::VkDescriptorType           descriptorType,
4192                                                                                                                                                                          ShaderInputInterface           shaderInterface,
4193                                                                                                                                                                          bool                                           isImmutable);
4194
4195         static vk::Move<vk::VkDescriptorSet>                    createDescriptorSet                             (const vk::DeviceInterface&                     vki,
4196                                                                                                                                                                          vk::VkDevice                                           device,
4197                                                                                                                                                                          vk::VkDescriptorType                           descriptorType,
4198                                                                                                                                                                          ShaderInputInterface                           shaderInterface,
4199                                                                                                                                                                          vk::VkDescriptorSetLayout                      layout,
4200                                                                                                                                                                          vk::VkDescriptorPool                           pool,
4201                                                                                                                                                                          bool                                                           isImmutable,
4202                                                                                                                                                                          const ImageSampleInstanceImages&       images);
4203
4204         static void                                                                             writeSamplerDescriptorSet               (const vk::DeviceInterface&                     vki,
4205                                                                                                                                                                          vk::VkDevice                                           device,
4206                                                                                                                                                                          ShaderInputInterface                           shaderInterface,
4207                                                                                                                                                                          bool                                                           isImmutable,
4208                                                                                                                                                                          const ImageSampleInstanceImages&       images,
4209                                                                                                                                                                          vk::VkDescriptorSet                            descriptorSet);
4210
4211         static void                                                                             writeImageSamplerDescriptorSet  (const vk::DeviceInterface&                     vki,
4212                                                                                                                                                                          vk::VkDevice                                           device,
4213                                                                                                                                                                          ShaderInputInterface                           shaderInterface,
4214                                                                                                                                                                          bool                                                           isImmutable,
4215                                                                                                                                                                          const ImageSampleInstanceImages&       images,
4216                                                                                                                                                                          vk::VkDescriptorSet                            descriptorSet);
4217
4218         void                                                                                    logTestPlan                                             (void) const;
4219         vk::VkPipelineLayout                                                    getPipelineLayout                               (void) const;
4220         void                                                                                    writeDrawCmdBuffer                              (vk::VkCmdBuffer cmd) const;
4221         tcu::TestStatus                                                                 verifyResultImage                               (const tcu::ConstPixelBufferAccess& result) const;
4222
4223         enum
4224         {
4225                 RENDER_SIZE = 128,
4226         };
4227
4228         const vk::VkDescriptorType                                              m_descriptorType;
4229         const vk::VkShaderStageFlags                                    m_stageFlags;
4230         const ShaderInputInterface                                              m_shaderInterface;
4231         const vk::VkImageViewType                                               m_viewType;
4232         const deUint32                                                                  m_baseMipLevel;
4233         const deUint32                                                                  m_baseArraySlice;
4234
4235         const ImageSampleInstanceImages                                 m_images;
4236         const vk::Unique<vk::VkDescriptorSetLayout>             m_descriptorSetLayout;
4237         const vk::Unique<vk::VkPipelineLayout>                  m_pipelineLayout;
4238         const vk::Unique<vk::VkDescriptorPool>                  m_descriptorPool;
4239         const vk::Unique<vk::VkDescriptorSet>                   m_descriptorSet;
4240 };
4241
4242 ImageSampleRenderInstance::ImageSampleRenderInstance (vkt::Context&                             context,
4243                                                                                                           bool                                          isPrimaryCmdBuf,
4244                                                                                                           vk::VkDescriptorType          descriptorType,
4245                                                                                                           vk::VkShaderStageFlags        stageFlags,
4246                                                                                                           ShaderInputInterface          shaderInterface,
4247                                                                                                           vk::VkImageViewType           viewType,
4248                                                                                                           deUint32                                      baseMipLevel,
4249                                                                                                           deUint32                                      baseArraySlice,
4250                                                                                                           bool                                          isImmutable)
4251         : SingleCmdRenderInstance       (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
4252         , m_descriptorType                      (descriptorType)
4253         , m_stageFlags                          (stageFlags)
4254         , m_shaderInterface                     (shaderInterface)
4255         , m_viewType                            (viewType)
4256         , m_baseMipLevel                        (baseMipLevel)
4257         , m_baseArraySlice                      (baseArraySlice)
4258         , m_images                                      (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutable)
4259         , m_descriptorSetLayout         (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_images))
4260         , m_pipelineLayout                      (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
4261         , m_descriptorPool                      (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface, isImmutable))
4262         , m_descriptorSet                       (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, isImmutable, m_images))
4263 {
4264 }
4265
4266 vk::Move<vk::VkDescriptorSetLayout> ImageSampleRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&            vki,
4267                                                                                                                                                                                   vk::VkDevice                                          device,
4268                                                                                                                                                                                   vk::VkDescriptorType                          descriptorType,
4269                                                                                                                                                                                   ShaderInputInterface                          shaderInterface,
4270                                                                                                                                                                                   vk::VkShaderStageFlags                        stageFlags,
4271                                                                                                                                                                                   const ImageSampleInstanceImages&      images)
4272 {
4273         const vk::VkSampler                             samplers[2] =
4274         {
4275                 images.getSamplerA(),
4276                 images.getSamplerB(),
4277         };
4278
4279         vk::DescriptorSetLayoutBuilder  builder;
4280
4281         // with samplers, separate texture at binding 0
4282         if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4283                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
4284
4285         // (combined)samplers follow
4286         switch (shaderInterface)
4287         {
4288                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4289                         builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4290                         break;
4291
4292                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
4293                         builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4294                         builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4295                         break;
4296
4297                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4298                         builder.addArraySamplerBinding(descriptorType, 2u, stageFlags, (images.isImmutable()) ? (samplers) : (DE_NULL));
4299                         break;
4300
4301                 default:
4302                         DE_FATAL("Impossible");
4303         }
4304
4305         return builder.build(vki, device);
4306 }
4307
4308 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout (const vk::DeviceInterface&      vki,
4309                                                                                                                                                                 vk::VkDevice                            device,
4310                                                                                                                                                                 vk::VkDescriptorSetLayout       descriptorSetLayout)
4311 {
4312         const vk::VkPipelineLayoutCreateInfo createInfo =
4313         {
4314                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
4315                 DE_NULL,
4316                 1,                                              // descriptorSetCount
4317                 &descriptorSetLayout,   // pSetLayouts
4318                 0u,                                             // pushConstantRangeCount
4319                 DE_NULL,                                // pPushConstantRanges
4320         };
4321         return vk::createPipelineLayout(vki, device, &createInfo);
4322 }
4323
4324 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool (const vk::DeviceInterface&      vki,
4325                                                                                                                                                                 vk::VkDevice                            device,
4326                                                                                                                                                                 vk::VkDescriptorType            descriptorType,
4327                                                                                                                                                                 ShaderInputInterface            shaderInterface,
4328                                                                                                                                                                 bool                                            isImmutable)
4329 {
4330         vk::DescriptorPoolBuilder builder;
4331
4332         if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4333         {
4334                 // separate samplers need image to sample
4335                 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
4336
4337                 // samplers needed only if they are specified in the descriptor set
4338                 if (!isImmutable)
4339                         builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER, getInterfaceNumResources(shaderInterface));
4340         }
4341         else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4342         {
4343                 // combined image samplers
4344                 builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, getInterfaceNumResources(shaderInterface));
4345         }
4346         else
4347                 DE_FATAL("Impossible");
4348
4349         return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
4350 }
4351
4352 vk::Move<vk::VkDescriptorSet> ImageSampleRenderInstance::createDescriptorSet (const vk::DeviceInterface&                vki,
4353                                                                                                                                                           vk::VkDevice                                          device,
4354                                                                                                                                                           vk::VkDescriptorType                          descriptorType,
4355                                                                                                                                                           ShaderInputInterface                          shaderInterface,
4356                                                                                                                                                           vk::VkDescriptorSetLayout                     layout,
4357                                                                                                                                                           vk::VkDescriptorPool                          pool,
4358                                                                                                                                                           bool                                                          isImmutable,
4359                                                                                                                                                           const ImageSampleInstanceImages&      images)
4360 {
4361         vk::Move<vk::VkDescriptorSet> descriptorSet = allocDescriptorSet(vki, device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
4362
4363         if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4364                 writeSamplerDescriptorSet(vki, device,  shaderInterface, isImmutable, images, *descriptorSet);
4365         else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4366                 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet);
4367         else
4368                 DE_FATAL("Impossible");
4369
4370         return descriptorSet;
4371 }
4372
4373 void ImageSampleRenderInstance::writeSamplerDescriptorSet (const vk::DeviceInterface&           vki,
4374                                                                                                                    vk::VkDevice                                         device,
4375                                                                                                                    ShaderInputInterface                         shaderInterface,
4376                                                                                                                    bool                                                         isImmutable,
4377                                                                                                                    const ImageSampleInstanceImages&     images,
4378                                                                                                                    vk::VkDescriptorSet                          descriptorSet)
4379 {
4380         const vk::VkDescriptorInfo              imageInfo                       = createDescriptorInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4381         const vk::VkDescriptorInfo              samplersInfos[2]        =
4382         {
4383                 createDescriptorInfo(images.getSamplerA()),
4384                 createDescriptorInfo(images.getSamplerB()),
4385         };
4386
4387         vk::DescriptorSetUpdateBuilder  builder;
4388
4389         // stand alone texture
4390         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
4391
4392         // samplers
4393         if (!isImmutable)
4394         {
4395                 switch (shaderInterface)
4396                 {
4397                         case SHADER_INPUT_SINGLE_DESCRIPTOR:
4398                                 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4399                                 break;
4400
4401                         case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
4402                                 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4403                                 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4404                                 break;
4405
4406                         case SHADER_INPUT_DESCRIPTOR_ARRAY:
4407                                 builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
4408                                 break;
4409
4410                         default:
4411                                 DE_FATAL("Impossible");
4412                 }
4413         }
4414
4415         builder.update(vki, device);
4416 }
4417
4418 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet (const vk::DeviceInterface&                      vki,
4419                                                                                                                                 vk::VkDevice                                            device,
4420                                                                                                                                 ShaderInputInterface                            shaderInterface,
4421                                                                                                                                 bool                                                            isImmutable,
4422                                                                                                                                 const ImageSampleInstanceImages&        images,
4423                                                                                                                                 vk::VkDescriptorSet                                     descriptorSet)
4424 {
4425         const vk::VkSampler                             samplers[2]                     =
4426         {
4427                 (isImmutable) ? (0) : (images.getSamplerA()),
4428                 (isImmutable) ? (0) : (images.getSamplerB()),
4429         };
4430         const vk::VkDescriptorInfo              imageSamplers[2]        =
4431         {
4432                 createDescriptorInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4433                 createDescriptorInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4434         };
4435
4436         vk::DescriptorSetUpdateBuilder  builder;
4437
4438         // combined image samplers
4439         switch (shaderInterface)
4440         {
4441                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4442                         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4443                         break;
4444
4445                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
4446                         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4447                         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
4448                         break;
4449
4450                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4451                         builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
4452                         break;
4453
4454                 default:
4455                         DE_FATAL("Impossible");
4456         }
4457
4458         builder.update(vki, device);
4459 }
4460
4461 void ImageSampleRenderInstance::logTestPlan (void) const
4462 {
4463         std::ostringstream msg;
4464
4465         msg << "Rendering 2x2 grid.\n";
4466
4467         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4468         {
4469                 msg << "Single descriptor set. Descriptor set contains "
4470                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4471                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
4472                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4473                             (const char*)DE_NULL)
4474                         << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
4475         }
4476         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4477         {
4478                 msg << "Single descriptor set. Descriptor set contains "
4479                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4480                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
4481                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4482                             (const char*)DE_NULL)
4483                         << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
4484         }
4485         else
4486                 DE_FATAL("Impossible");
4487
4488         msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4489
4490         if (m_baseMipLevel)
4491                 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4492         if (m_baseArraySlice)
4493                 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4494
4495         if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
4496                 msg << "Sampler mode is LINEAR, with WRAP\n";
4497         else
4498                 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
4499
4500         if (m_stageFlags == 0u)
4501         {
4502                 msg << "Descriptors are not accessed in any shader stage.\n";
4503         }
4504         else
4505         {
4506                 msg << "Color in each cell is fetched using the descriptor(s):\n";
4507
4508                 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4509                 {
4510                         msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4511
4512                         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4513                         {
4514                                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
4515
4516                                 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4517                                         msg << " using sampler " << srcResourceNdx;
4518                                 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4519                                         msg << " from combined image sampler " << srcResourceNdx;
4520                                 else
4521                                         DE_FATAL("Impossible");
4522                         }
4523                         msg << "\n";
4524                 }
4525
4526                 msg << "Descriptors are accessed in {"
4527                         << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)                      ? (" vertex")                   : (""))
4528                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0)        ? (" tess_control")             : (""))
4529                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0)     ? (" tess_evaluation")  : (""))
4530                         << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)            ? (" geometry")                 : (""))
4531                         << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)            ? (" fragment")                 : (""))
4532                         << " } stages.";
4533         }
4534
4535         m_context.getTestContext().getLog()
4536                 << tcu::TestLog::Message
4537                 << msg.str()
4538                 << tcu::TestLog::EndMessage;
4539 }
4540
4541 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout (void) const
4542 {
4543         return *m_pipelineLayout;
4544 }
4545
4546 void ImageSampleRenderInstance::writeDrawCmdBuffer (vk::VkCmdBuffer cmd) const
4547 {
4548         m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
4549         m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles)
4550 }
4551
4552 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
4553 {
4554         const tcu::Vec4         green           (0.0f, 1.0f, 0.0f, 1.0f);
4555         const tcu::Vec4         yellow          (1.0f, 1.0f, 0.0f, 1.0f);
4556         const bool                      doFetch         = (m_stageFlags != 0u); // no active stages? Then don't fetch
4557         const tcu::Vec4         sample0         = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(0));
4558         const tcu::Vec4         sample1         = (!doFetch) ? (green)  : (m_images.fetchSampleValue(1));
4559         const tcu::Vec4         sample2         = (!doFetch) ? (green)  : (m_images.fetchSampleValue(2));
4560         const tcu::Vec4         sample3         = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(3));
4561         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
4562         tcu::Surface            reference       (m_targetSize.x(), m_targetSize.y());
4563
4564         drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
4565
4566         if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, threshold, tcu::COMPARE_LOG_RESULT))
4567                 return tcu::TestStatus::fail("Image verification failed");
4568         else
4569                 return tcu::TestStatus::pass("Pass");
4570 }
4571
4572 class ImageSampleComputeInstance : public vkt::TestInstance
4573 {
4574 public:
4575                                                                                         ImageSampleComputeInstance              (vkt::Context&                  context,
4576                                                                                                                                                          vk::VkDescriptorType   descriptorType,
4577                                                                                                                                                          ShaderInputInterface   shaderInterface,
4578                                                                                                                                                          vk::VkImageViewType    viewType,
4579                                                                                                                                                          deUint32                               baseMipLevel,
4580                                                                                                                                                          deUint32                               baseArraySlice,
4581                                                                                                                                                          bool                                   isImmutableSampler);
4582
4583 private:
4584         vk::Move<vk::VkDescriptorSetLayout>             createDescriptorSetLayout               (void) const;
4585         vk::Move<vk::VkDescriptorPool>                  createDescriptorPool                    (void) const;
4586         vk::Move<vk::VkDescriptorSet>                   createDescriptorSet                             (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
4587         void                                                                    writeImageSamplerDescriptorSet  (vk::VkDescriptorSet descriptorSet) const;
4588         void                                                                    writeSamplerDescriptorSet               (vk::VkDescriptorSet descriptorSet) const;
4589
4590         tcu::TestStatus                                                 iterate                                                 (void);
4591         void                                                                    logTestPlan                                             (void) const;
4592         tcu::TestStatus                                                 testResourceAccess                              (void);
4593
4594         const vk::VkDescriptorType                              m_descriptorType;
4595         const ShaderInputInterface                              m_shaderInterface;
4596         const vk::VkImageViewType                               m_viewType;
4597         const deUint32                                                  m_baseMipLevel;
4598         const deUint32                                                  m_baseArraySlice;
4599         const bool                                                              m_isImmutableSampler;
4600
4601         const vk::DeviceInterface&                              m_vki;
4602         const vk::VkDevice                                              m_device;
4603         const vk::VkQueue                                               m_queue;
4604         const deUint32                                                  m_queueFamilyIndex;
4605         vk::Allocator&                                                  m_allocator;
4606
4607         const ComputeInstanceResultBuffer               m_result;
4608         const ImageSampleInstanceImages                 m_images;
4609 };
4610
4611 ImageSampleComputeInstance::ImageSampleComputeInstance (Context&                                context,
4612                                                                                                                 vk::VkDescriptorType    descriptorType,
4613                                                                                                                 ShaderInputInterface    shaderInterface,
4614                                                                                                                 vk::VkImageViewType             viewType,
4615                                                                                                                 deUint32                                baseMipLevel,
4616                                                                                                                 deUint32                                baseArraySlice,
4617                                                                                                                 bool                                    isImmutableSampler)
4618         : vkt::TestInstance             (context)
4619         , m_descriptorType              (descriptorType)
4620         , m_shaderInterface             (shaderInterface)
4621         , m_viewType                    (viewType)
4622         , m_baseMipLevel                (baseMipLevel)
4623         , m_baseArraySlice              (baseArraySlice)
4624         , m_isImmutableSampler  (isImmutableSampler)
4625         , m_vki                                 (context.getDeviceInterface())
4626         , m_device                              (context.getDevice())
4627         , m_queue                               (context.getUniversalQueue())
4628         , m_queueFamilyIndex    (context.getUniversalQueueFamilyIndex())
4629         , m_allocator                   (context.getDefaultAllocator())
4630         , m_result                              (m_vki, m_device, m_allocator)
4631         , m_images                              (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutableSampler)
4632 {
4633 }
4634
4635 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout (void) const
4636 {
4637         const vk::VkSampler                             samplers[2] =
4638         {
4639                 m_images.getSamplerA(),
4640                 m_images.getSamplerB(),
4641         };
4642
4643         vk::DescriptorSetLayoutBuilder  builder;
4644
4645         // result buffer
4646         builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4647
4648         // with samplers, separate texture at binding 0
4649         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4650                 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
4651
4652         // (combined)samplers follow
4653         switch (m_shaderInterface)
4654         {
4655                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4656                         builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4657                         break;
4658
4659                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
4660                         builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL));
4661                         builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL));
4662                         break;
4663
4664                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4665                         builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (samplers) : (DE_NULL));
4666                         break;
4667
4668                 default:
4669                         DE_FATAL("Impossible");
4670         };
4671
4672         return builder.build(m_vki, m_device);
4673 }
4674
4675 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool (void) const
4676 {
4677         vk::DescriptorPoolBuilder builder;
4678
4679         builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
4680         builder.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface));
4681
4682         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4683                 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
4684
4685         return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
4686 }
4687
4688 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
4689 {
4690         vk::Move<vk::VkDescriptorSet> descriptorSet = allocDescriptorSet(m_vki, m_device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
4691
4692         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4693                 writeSamplerDescriptorSet(*descriptorSet);
4694         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4695                 writeImageSamplerDescriptorSet(*descriptorSet);
4696         else
4697                 DE_FATAL("Impossible");
4698
4699         return descriptorSet;
4700 }
4701
4702 void ImageSampleComputeInstance::writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
4703 {
4704         const vk::VkDescriptorInfo              resultInfo                      = createDescriptorInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4705         const vk::VkDescriptorInfo              imageInfo                       = createDescriptorInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
4706         const vk::VkDescriptorInfo              samplersInfos[2]        =
4707         {
4708                 createDescriptorInfo(m_images.getSamplerA()),
4709                 createDescriptorInfo(m_images.getSamplerB()),
4710         };
4711
4712         vk::DescriptorSetUpdateBuilder  builder;
4713
4714         // result
4715         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4716
4717         // stand alone texture
4718         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo);
4719
4720         // samplers
4721         if (!m_isImmutableSampler)
4722         {
4723                 switch (m_shaderInterface)
4724                 {
4725                         case SHADER_INPUT_SINGLE_DESCRIPTOR:
4726                                 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4727                                 break;
4728
4729                         case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
4730                                 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]);
4731                                 builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(3u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]);
4732                                 break;
4733
4734                         case SHADER_INPUT_DESCRIPTOR_ARRAY:
4735                                 builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos);
4736                                 break;
4737
4738                         default:
4739                                 DE_FATAL("Impossible");
4740                 }
4741         }
4742
4743         builder.update(m_vki, m_device);
4744 }
4745
4746 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) const
4747 {
4748         const vk::VkDescriptorInfo              resultInfo                      = createDescriptorInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
4749         const vk::VkSampler                             samplers[2]                     =
4750         {
4751                 (m_isImmutableSampler) ? (0) : (m_images.getSamplerA()),
4752                 (m_isImmutableSampler) ? (0) : (m_images.getSamplerB()),
4753         };
4754         const vk::VkDescriptorInfo              imageSamplers[2]        =
4755         {
4756                 createDescriptorInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4757                 createDescriptorInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL),
4758         };
4759
4760         vk::DescriptorSetUpdateBuilder  builder;
4761
4762         // result
4763         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
4764
4765         // combined image samplers
4766         switch (m_shaderInterface)
4767         {
4768                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
4769                         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4770                         break;
4771
4772                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
4773                         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]);
4774                         builder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]);
4775                         break;
4776
4777                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
4778                         builder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers);
4779                         break;
4780
4781                 default:
4782                         DE_FATAL("Impossible");
4783         }
4784
4785         builder.update(m_vki, m_device);
4786 }
4787
4788 tcu::TestStatus ImageSampleComputeInstance::iterate (void)
4789 {
4790         logTestPlan();
4791         return testResourceAccess();
4792 }
4793
4794 void ImageSampleComputeInstance::logTestPlan (void) const
4795 {
4796         std::ostringstream msg;
4797
4798         msg << "Accessing resource in a compute program.\n";
4799
4800         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4801         {
4802                 msg << "Single descriptor set. Descriptor set contains "
4803                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4804                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
4805                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4806                             (const char*)DE_NULL)
4807                         << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n";
4808         }
4809         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4810         {
4811                 msg << "Single descriptor set. Descriptor set contains "
4812                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
4813                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
4814                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
4815                             (const char*)DE_NULL)
4816                         << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n";
4817         }
4818         else
4819                 DE_FATAL("Impossible");
4820
4821         msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n";
4822
4823         if (m_baseMipLevel)
4824                 msg << "Image view base mip level = " << m_baseMipLevel << "\n";
4825         if (m_baseArraySlice)
4826                 msg << "Image view base array slice = " << m_baseArraySlice << "\n";
4827
4828         if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)
4829                 msg << "Sampler mode is LINEAR, with WRAP\n";
4830         else
4831                 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n";
4832
4833         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4834         {
4835                 msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx);
4836
4837                 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
4838                 {
4839                         const int srcResourceNdx = (resultNdx % 2); // ABAB source
4840
4841                         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
4842                                 msg << " using sampler " << srcResourceNdx;
4843                         else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
4844                                 msg << " from combined image sampler " << srcResourceNdx;
4845                         else
4846                                 DE_FATAL("Impossible");
4847                 }
4848                 msg << "\n";
4849         }
4850
4851         m_context.getTestContext().getLog()
4852                 << tcu::TestLog::Message
4853                 << msg.str()
4854                 << tcu::TestLog::EndMessage;
4855 }
4856
4857 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess (void)
4858 {
4859         const vk::Unique<vk::VkDescriptorSetLayout>             descriptorSetLayout     (createDescriptorSetLayout());
4860         const vk::Unique<vk::VkDescriptorPool>                  descriptorPool          (createDescriptorPool());
4861         const vk::Unique<vk::VkDescriptorSet>                   descriptorSet           (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
4862         const ComputePipeline                                                   pipeline                        (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
4863
4864         const vk::VkDescriptorSet                                               descriptorSets[]        = { *descriptorSet };
4865         const int                                                                               numDescriptorSets       = DE_LENGTH_OF_ARRAY(descriptorSets);
4866         const deUint32* const                                                   dynamicOffsets          = DE_NULL;
4867         const int                                                                               numDynamicOffsets       = 0;
4868         const void*     const*                                                          preBarriers                     = DE_NULL;
4869         const int                                                                               numPreBarriers          = 0;
4870         const void* const                                                               postBarriers[]          = { m_result.getResultReadBarrier() };
4871         const int                                                                               numPostBarriers         = DE_LENGTH_OF_ARRAY(postBarriers);
4872
4873         const ComputeCommand                                                    compute                         (m_vki,
4874                                                                                                                                                  m_device,
4875                                                                                                                                                  pipeline.getPipeline(),
4876                                                                                                                                                  pipeline.getPipelineLayout(),
4877                                                                                                                                                  tcu::UVec3(4, 1, 1),
4878                                                                                                                                                  numDescriptorSets,     descriptorSets,
4879                                                                                                                                                  numDynamicOffsets,     dynamicOffsets,
4880                                                                                                                                                  numPreBarriers,        preBarriers,
4881                                                                                                                                                  numPostBarriers,       postBarriers);
4882
4883         tcu::Vec4                                                                               results[4];
4884         bool                                                                                    anyResultSet            = false;
4885         bool                                                                                    allResultsOk            = true;
4886
4887         compute.submitAndWait(m_queueFamilyIndex, m_queue);
4888         m_result.readResultContentsTo(&results);
4889
4890         // verify
4891         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
4892         {
4893                 const tcu::Vec4 result                          = results[resultNdx];
4894                 const tcu::Vec4 reference                       = m_images.fetchSampleValue(resultNdx);
4895
4896                 // source image is high-frequency so the threshold is quite large to tolerate sampling errors
4897                 const tcu::Vec4 samplingThreshold       = tcu::Vec4(8.0f / 255.0f);
4898
4899                 if (result != tcu::Vec4(-1.0f))
4900                         anyResultSet = true;
4901
4902                 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold)))
4903                 {
4904                         allResultsOk = false;
4905
4906                         m_context.getTestContext().getLog()
4907                                 << tcu::TestLog::Message
4908                                 << "Test sample " << resultNdx << ":\n"
4909                                 << "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx) << "\n"
4910                                 << "\tError expected " << reference << ", got " << result
4911                                 << tcu::TestLog::EndMessage;
4912                 }
4913         }
4914
4915         // read back and verify
4916         if (allResultsOk)
4917                 return tcu::TestStatus::pass("Pass");
4918         else if (anyResultSet)
4919                 return tcu::TestStatus::fail("Invalid result values");
4920         else
4921         {
4922                 m_context.getTestContext().getLog()
4923                         << tcu::TestLog::Message
4924                         << "Result buffer was not written to."
4925                         << tcu::TestLog::EndMessage;
4926                 return tcu::TestStatus::fail("Result buffer was not written to");
4927         }
4928 }
4929
4930 class ImageDescriptorCase : public QuadrantRendederCase
4931 {
4932 public:
4933         enum
4934         {
4935                 FLAG_BASE_MIP   = (1u << 1u),
4936                 FLAG_BASE_SLICE = (1u << 2u),
4937         };
4938         // enum continues where resource flags ends
4939         DE_STATIC_ASSERT((deUint32)FLAG_BASE_MIP == (deUint32)RESOURCE_FLAG_LAST);
4940
4941                                                                 ImageDescriptorCase                     (tcu::TestContext&              testCtx,
4942                                                                                                                          const char*                    name,
4943                                                                                                                          const char*                    description,
4944                                                                                                                          bool                                   isPrimaryCmdBuf,
4945                                                                                                                          vk::VkDescriptorType   descriptorType,
4946                                                                                                                          vk::VkShaderStageFlags exitingStages,
4947                                                                                                                          vk::VkShaderStageFlags activeStages,
4948                                                                                                                          ShaderInputInterface   shaderInterface,
4949                                                                                                                          vk::VkImageViewType    viewType,
4950                                                                                                                          deUint32                               flags);
4951
4952 private:
4953         std::string                                     genExtensionDeclarations        (vk::VkShaderStage stage) const;
4954         std::string                                     genResourceDeclarations         (vk::VkShaderStage stage, int numUsedBindings) const;
4955         std::string                                     genFetchCoordStr                        (int fetchPosNdx) const;
4956         std::string                                     genSampleCoordStr                       (int samplePosNdx) const;
4957         std::string                                     genResourceAccessSource         (vk::VkShaderStage stage) const;
4958         std::string                                     genNoAccessSource                       (void) const;
4959
4960         vkt::TestInstance*                      createInstance                          (vkt::Context& context) const;
4961
4962 private:
4963         const bool                                      m_isPrimaryCmdBuf;
4964         const vk::VkDescriptorType      m_descriptorType;
4965         const ShaderInputInterface      m_shaderInterface;
4966         const vk::VkImageViewType       m_viewType;
4967         const deUint32                          m_baseMipLevel;
4968         const deUint32                          m_baseArraySlice;
4969         const bool                                      m_isImmutableSampler;
4970 };
4971
4972 ImageDescriptorCase::ImageDescriptorCase (tcu::TestContext&                     testCtx,
4973                                                                                   const char*                           name,
4974                                                                                   const char*                           description,
4975                                                                                   bool                                          isPrimaryCmdBuf,
4976                                                                                   vk::VkDescriptorType          descriptorType,
4977                                                                                   vk::VkShaderStageFlags        exitingStages,
4978                                                                                   vk::VkShaderStageFlags        activeStages,
4979                                                                                   ShaderInputInterface          shaderInterface,
4980                                                                                   vk::VkImageViewType           viewType,
4981                                                                                   deUint32                                      flags)
4982         : QuadrantRendederCase  (testCtx, name, description,
4983                                                          // \note 1D textures are not supported in ES
4984                                                          (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? glu::GLSL_VERSION_440 : glu::GLSL_VERSION_310_ES,
4985                                                          exitingStages, activeStages)
4986         , m_isPrimaryCmdBuf             (isPrimaryCmdBuf)
4987         , m_descriptorType              (descriptorType)
4988         , m_shaderInterface             (shaderInterface)
4989         , m_viewType                    (viewType)
4990         , m_baseMipLevel                (((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u))
4991         , m_baseArraySlice              (((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u))
4992         , m_isImmutableSampler  ((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0)
4993 {
4994 }
4995
4996 std::string ImageDescriptorCase::genExtensionDeclarations (vk::VkShaderStage stage) const
4997 {
4998         DE_UNREF(stage);
4999
5000         if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
5001                 return "#extension GL_OES_texture_cube_map_array : require\n";
5002         else
5003                 return "";
5004 }
5005
5006 std::string ImageDescriptorCase::genResourceDeclarations (vk::VkShaderStage stage, int numUsedBindings) const
5007 {
5008         DE_UNREF(stage);
5009
5010         // Vulkan-style resources are arrays implicitly, OpenGL-style are not
5011         const std::string       dimensionBase   = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)            ? ("1D")
5012                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)            ? ("2D")
5013                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                                                                                     ? ("3D")
5014                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)        ? ("Cube")
5015                                                                                 : (DE_NULL);
5016         const std::string       dimensionArray  = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)            ? ("1DArray")
5017                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)            ? ("2DArray")
5018                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                                                                                     ? ("3D")
5019                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)        ? ("CubeArray")
5020                                                                                 : (DE_NULL);
5021         const std::string       dimension               = isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase;
5022
5023         switch (m_shaderInterface)
5024         {
5025                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5026                 {
5027                         switch (m_descriptorType)
5028                         {
5029                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5030                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n"
5031                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler;\n";
5032                                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5033                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler;\n";
5034                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5035                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n";
5036                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5037                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image;\n";
5038                                 default:
5039                                         DE_FATAL("invalid descriptor");
5040                                         return "";
5041                         }
5042                 }
5043
5044                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
5045                         switch (m_descriptorType)
5046                         {
5047                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5048                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n"
5049                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplerA;\n"
5050                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n";
5051                                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5052                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerA;\n"
5053                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerB;\n";
5054                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5055                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTextureA;\n"
5056                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimensionBase + " u_separateTextureB;\n";
5057                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5058                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_imageA;\n"
5059                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ", rgba8) readonly uniform highp image" + dimension + " u_imageB;\n";
5060                                 default:
5061                                         DE_FATAL("invalid descriptor");
5062                                         return "";
5063                         }
5064
5065                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5066                         switch (m_descriptorType)
5067                         {
5068                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5069                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n"
5070                                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplers[2];\n";
5071                                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5072                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler[2];\n";
5073                                 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5074                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture[2];\n";
5075                                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5076                                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image[2];\n";
5077                                 default:
5078                                         DE_FATAL("invalid descriptor");
5079                                         return "";
5080                         }
5081
5082                 default:
5083                         DE_FATAL("Impossible");
5084                         return "";
5085         }
5086 }
5087
5088 std::string ImageDescriptorCase::genFetchCoordStr (int fetchPosNdx) const
5089 {
5090         DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
5091         const tcu::IVec3 fetchPos = ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx);
5092
5093         if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
5094         {
5095                 return de::toString(fetchPos.x());
5096         }
5097         else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
5098         {
5099                 std::ostringstream buf;
5100                 buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")";
5101                 return buf.str();
5102         }
5103         else
5104         {
5105                 std::ostringstream buf;
5106                 buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")";
5107                 return buf.str();
5108         }
5109 }
5110
5111 std::string ImageDescriptorCase::genSampleCoordStr (int samplePosNdx) const
5112 {
5113         DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
5114         const tcu::Vec4 fetchPos = ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx);
5115
5116         if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D)
5117         {
5118                 std::ostringstream buf;
5119                 buf << "float(" << fetchPos.x() << ")";
5120                 return buf.str();
5121         }
5122         else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D)
5123         {
5124                 std::ostringstream buf;
5125                 buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))";
5126                 return buf.str();
5127         }
5128         else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
5129         {
5130                 std::ostringstream buf;
5131                 buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "), float(" << fetchPos.w() << "))";
5132                 return buf.str();
5133         }
5134         else
5135         {
5136                 std::ostringstream buf;
5137                 buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))";
5138                 return buf.str();
5139         }
5140 }
5141
5142 std::string ImageDescriptorCase::genResourceAccessSource (vk::VkShaderStage stage) const
5143 {
5144         DE_UNREF(stage);
5145
5146         const char* const       dimensionArray  = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)            ? ("1DArray")
5147                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY)            ? ("2DArray")
5148                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D)                                                                                                                     ? ("3D")
5149                                                                                 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)        ? ("CubeArray")
5150                                                                                 : (DE_NULL);
5151         const char* const       accessPostfixA  = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)         ? ("")
5152                                                                                 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS)      ? ("A")
5153                                                                                 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)          ? ("[0]")
5154                                                                                 : (DE_NULL);
5155         const char* const       accessPostfixB  = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)         ? ("")
5156                                                                                 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS)      ? ("B")
5157                                                                                 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)          ? ("[1]")
5158                                                                                 : (DE_NULL);
5159
5160         switch (m_descriptorType)
5161         {
5162                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5163                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5164                 {
5165                         const std::string       coodStr[4]      =
5166                         {
5167                                 genSampleCoordStr(0),
5168                                 genSampleCoordStr(1),
5169                                 genSampleCoordStr(2),
5170                                 genSampleCoordStr(3),
5171                         };
5172                         std::ostringstream      buf;
5173
5174                         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER)
5175                         {
5176                                 buf << "        if (quadrant_id == 0)\n"
5177                                         << "            result_color = textureLod(sampler" << dimensionArray << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[0] << ", 0.0);\n"
5178                                         << "    else if (quadrant_id == 1)\n"
5179                                         << "            result_color = textureLod(sampler" << dimensionArray << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[1] << ", 0.0);\n"
5180                                         << "    else if (quadrant_id == 2)\n"
5181                                         << "            result_color = textureLod(sampler" << dimensionArray << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[2] << ", 0.0);\n"
5182                                         << "    else\n"
5183                                         << "            result_color = textureLod(sampler" << dimensionArray << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[3] << ", 0.0);\n";
5184                         }
5185                         else
5186                         {
5187                                 buf << "        if (quadrant_id == 0)\n"
5188                                         << "            result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[0] << ", 0.0);\n"
5189                                         << "    else if (quadrant_id == 1)\n"
5190                                         << "            result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[1] << ", 0.0);\n"
5191                                         << "    else if (quadrant_id == 2)\n"
5192                                         << "            result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[2] << ", 0.0);\n"
5193                                         << "    else\n"
5194                                         << "            result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[3] << ", 0.0);\n";
5195                         }
5196
5197                         return buf.str();
5198                 }
5199
5200                 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5201                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5202                 {
5203                         const std::string       coodStr[4]      =
5204                         {
5205                                 genFetchCoordStr(0),
5206                                 genFetchCoordStr(1),
5207                                 genFetchCoordStr(2),
5208                                 genFetchCoordStr(3),
5209                         };
5210                         std::ostringstream      buf;
5211
5212                         if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
5213                         {
5214                                 buf << "        if (quadrant_id == 0)\n"
5215                                         << "            result_color = textureFetch(u_separateTexture" << accessPostfixA << ", " << coodStr[0] << ", 0);\n"
5216                                         << "    else if (quadrant_id == 1)\n"
5217                                         << "            result_color = textureFetch(u_separateTexture" << accessPostfixB << ", " << coodStr[1] << ", 0);\n"
5218                                         << "    else if (quadrant_id == 2)\n"
5219                                         << "            result_color = textureFetch(u_separateTexture" << accessPostfixA << ", " << coodStr[2] << ", 0);\n"
5220                                         << "    else\n"
5221                                         << "            result_color = textureFetch(u_separateTexture" << accessPostfixB << ", " << coodStr[3] << ", 0);\n";
5222                         }
5223                         else
5224                         {
5225                                 buf << "        if (quadrant_id == 0)\n"
5226                                         << "            result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[0] << ");\n"
5227                                         << "    else if (quadrant_id == 1)\n"
5228                                         << "            result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[1] << ");\n"
5229                                         << "    else if (quadrant_id == 2)\n"
5230                                         << "            result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[2] << ");\n"
5231                                         << "    else\n"
5232                                         << "            result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[3] << ");\n";
5233                         }
5234
5235                         return buf.str();
5236                 }
5237
5238                 default:
5239                         DE_FATAL("invalid descriptor");
5240                         return "";
5241         }
5242 }
5243
5244 std::string ImageDescriptorCase::genNoAccessSource (void) const
5245 {
5246         return "        if (quadrant_id == 1 || quadrant_id == 2)\n"
5247                         "               result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
5248                         "       else\n"
5249                         "               result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
5250 }
5251
5252 vkt::TestInstance* ImageDescriptorCase::createInstance (vkt::Context& context) const
5253 {
5254         switch (m_descriptorType)
5255         {
5256                 case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
5257                 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
5258                         if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
5259                         {
5260                                 DE_ASSERT(m_isPrimaryCmdBuf);
5261                                 return new ImageSampleComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
5262                         }
5263                         else
5264                                 return new ImageSampleRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler);
5265
5266                 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
5267                 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
5268                         if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
5269                         {
5270                                 DE_ASSERT(m_isPrimaryCmdBuf);
5271                                 return new ImageFetchComputeInstance(context, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
5272                         }
5273                         else
5274                                 return new ImageFetchRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice);
5275
5276                 default:
5277                         DE_FATAL("Impossible");
5278                         return DE_NULL;
5279         }
5280 }
5281
5282 class TexelBufferInstanceBuffers
5283 {
5284 public:
5285                                                                                 TexelBufferInstanceBuffers      (const vk::DeviceInterface&             vki,
5286                                                                                                                                          vk::VkDevice                                   device,
5287                                                                                                                                          vk::Allocator&                                 allocator,
5288                                                                                                                                          vk::VkDescriptorType                   descriptorType,
5289                                                                                                                                          int                                                    numTexelBuffers,
5290                                                                                                                                          bool                                                   hasViewOffset);
5291
5292 private:
5293         static vk::Move<vk::VkBuffer>           createBuffer                            (const vk::DeviceInterface&             vki,
5294                                                                                                                                          vk::VkDevice                                   device,
5295                                                                                                                                          vk::Allocator&                                 allocator,
5296                                                                                                                                          vk::VkDescriptorType                   descriptorType,
5297                                                                                                                                          de::MovePtr<vk::Allocation>    *outAllocation);
5298
5299         static vk::Move<vk::VkBufferView>       createBufferView                        (const vk::DeviceInterface&             vki,
5300                                                                                                                                          vk::VkDevice                                   device,
5301                                                                                                                                          const tcu::TextureFormat&              textureFormat,
5302                                                                                                                                          deUint32                                               offset,
5303                                                                                                                                          vk::VkBuffer                                   buffer);
5304
5305         static vk::VkBufferMemoryBarrier        createBarrier                           (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer);
5306
5307         void                                                            populateSourceBuffer            (const tcu::PixelBufferAccess& access);
5308         void                                                            uploadData                                      (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data);
5309
5310 public:
5311         static int                                                      getFetchPos                                     (int fetchPosNdx);
5312         tcu::Vec4                                                       fetchTexelValue                         (int fetchPosNdx) const;
5313
5314         inline int                                                      getNumTexelBuffers                      (void) const { return m_numTexelBuffers;        }
5315         const tcu::TextureFormat&                       getTextureFormat                        (void) const { return m_imageFormat;            }
5316         inline vk::VkBufferView                         getBufferViewA                          (void) const { return *m_bufferViewA;           }
5317         inline vk::VkBufferView                         getBufferViewB                          (void) const { return *m_bufferViewB;           }
5318         inline const void*                                      getBufferInitBarrierA           (void) const { return &m_bufferBarrierA;        }
5319         inline const void*                                      getBufferInitBarrierB           (void) const { return &m_bufferBarrierB;        }
5320
5321 private:
5322         enum
5323         {
5324                 BUFFER_SIZE                     = 512,
5325                 VIEW_OFFSET_VALUE       = 256,
5326                 VIEW_DATA_SIZE          = 256,  //!< size in bytes
5327                 VIEW_WIDTH                      = 64,   //!< size in pixels
5328         };
5329         enum
5330         {
5331                 // some arbitrary points
5332                 SAMPLE_POINT_0 = 6,
5333                 SAMPLE_POINT_1 = 51,
5334                 SAMPLE_POINT_2 = 42,
5335                 SAMPLE_POINT_3 = 25,
5336         };
5337
5338         const deUint32                                          m_numTexelBuffers;
5339         const tcu::TextureFormat                        m_imageFormat;
5340         const deUint32                                          m_viewOffset;
5341
5342         de::ArrayBuffer<deUint8>                        m_sourceBufferA;
5343         de::ArrayBuffer<deUint8>                        m_sourceBufferB;
5344         const tcu::ConstPixelBufferAccess       m_sourceViewA;
5345         const tcu::ConstPixelBufferAccess       m_sourceViewB;
5346
5347         de::MovePtr<vk::Allocation>                     m_bufferMemoryA;
5348         de::MovePtr<vk::Allocation>                     m_bufferMemoryB;
5349         const vk::Unique<vk::VkBuffer>          m_bufferA;
5350         const vk::Unique<vk::VkBuffer>          m_bufferB;
5351         const vk::Unique<vk::VkBufferView>      m_bufferViewA;
5352         const vk::Unique<vk::VkBufferView>      m_bufferViewB;
5353         const vk::VkBufferMemoryBarrier         m_bufferBarrierA;
5354         const vk::VkBufferMemoryBarrier         m_bufferBarrierB;
5355 };
5356
5357 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers (const vk::DeviceInterface&              vki,
5358                                                                                                                 vk::VkDevice                                    device,
5359                                                                                                                 vk::Allocator&                                  allocator,
5360                                                                                                                 vk::VkDescriptorType                    descriptorType,
5361                                                                                                                 int                                                             numTexelBuffers,
5362                                                                                                                 bool                                                    hasViewOffset)
5363         : m_numTexelBuffers     (numTexelBuffers)
5364         , m_imageFormat         (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8)
5365         , m_viewOffset          ((hasViewOffset) ? ((deUint32)VIEW_OFFSET_VALUE) : (0u))
5366         , m_sourceBufferA       (BUFFER_SIZE)
5367         , m_sourceBufferB       ((numTexelBuffers == 1)
5368                                                         ? (0u)
5369                                                         : ((size_t)BUFFER_SIZE))
5370         , m_sourceViewA         (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferA.getElementPtr(m_viewOffset))
5371         , m_sourceViewB         (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferB.getElementPtr(m_viewOffset))
5372         , m_bufferMemoryA       (DE_NULL)
5373         , m_bufferMemoryB       (DE_NULL)
5374         , m_bufferA                     (createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryA))
5375         , m_bufferB                     ((numTexelBuffers == 1)
5376                                                         ? vk::Move<vk::VkBuffer>()
5377                                                         : createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryB))
5378         , m_bufferViewA         (createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferA))
5379         , m_bufferViewB         ((numTexelBuffers == 1)
5380                                                         ? vk::Move<vk::VkBufferView>()
5381                                                         : createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferB))
5382         , m_bufferBarrierA      (createBarrier(descriptorType, *m_bufferA))
5383         , m_bufferBarrierB      (createBarrier(descriptorType, *m_bufferB))
5384 {
5385         DE_ASSERT(numTexelBuffers == 1 || numTexelBuffers == 2);
5386         DE_ASSERT(VIEW_WIDTH * m_imageFormat.getPixelSize() == VIEW_DATA_SIZE);
5387         DE_ASSERT(BUFFER_SIZE % m_imageFormat.getPixelSize() == 0);
5388
5389         // specify and upload
5390
5391         populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferA.getPtr()));
5392         uploadData(vki, device, *m_bufferMemoryA, m_sourceBufferA);
5393
5394         if (numTexelBuffers == 2)
5395         {
5396                 populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferB.getPtr()));
5397                 uploadData(vki, device, *m_bufferMemoryB, m_sourceBufferB);
5398         }
5399 }
5400
5401 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer (const vk::DeviceInterface&             vki,
5402                                                                                                                                  vk::VkDevice                                   device,
5403                                                                                                                                  vk::Allocator&                                 allocator,
5404                                                                                                                                  vk::VkDescriptorType                   descriptorType,
5405                                                                                                                                  de::MovePtr<vk::Allocation>    *outAllocation)
5406 {
5407         const vk::VkBufferUsageFlags    usage           = (isUniformDescriptorType(descriptorType)) ? (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
5408         const vk::VkBufferCreateInfo    createInfo      =
5409         {
5410                 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
5411                 DE_NULL,
5412                 (vk::VkDeviceSize)BUFFER_SIZE,          // size
5413                 usage,                                                          // usage
5414                 0u,                                                                     // flags
5415                 vk::VK_SHARING_MODE_EXCLUSIVE,          // sharingMode
5416                 0u,                                                                     // queueFamilyCount
5417                 DE_NULL,                                                        // pQueueFamilyIndices
5418         };
5419         vk::Move<vk::VkBuffer>                  buffer          (vk::createBuffer(vki, device, &createInfo));
5420         de::MovePtr<vk::Allocation>             allocation      (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible));
5421
5422         *outAllocation = allocation;
5423         return buffer;
5424 }
5425
5426 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView (const vk::DeviceInterface&             vki,
5427                                                                                                                                                  vk::VkDevice                                   device,
5428                                                                                                                                                  const tcu::TextureFormat&              textureFormat,
5429                                                                                                                                                  deUint32                                               offset,
5430                                                                                                                                                  vk::VkBuffer                                   buffer)
5431 {
5432         const vk::VkBufferViewCreateInfo createInfo =
5433         {
5434                 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
5435                 DE_NULL,
5436                 buffer,                                                                 // buffer
5437                 mapToVkTextureFormat(textureFormat),    // format
5438                 (vk::VkDeviceSize)offset,                               // offset
5439                 (vk::VkDeviceSize)VIEW_DATA_SIZE                // range
5440         };
5441         return vk::createBufferView(vki, device, &createInfo);
5442 }
5443
5444 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer)
5445 {
5446         const vk::VkMemoryInputFlags    inputBit        = (isUniformDescriptorType(descriptorType)) ? (vk::VK_MEMORY_INPUT_UNIFORM_READ_BIT) : (vk::VK_MEMORY_INPUT_SHADER_READ_BIT);
5447         const vk::VkBufferMemoryBarrier barrier         =
5448         {
5449                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
5450                 DE_NULL,
5451                 vk::VK_MEMORY_OUTPUT_HOST_WRITE_BIT,    // outputMask
5452                 inputBit,                                                               // inputMask
5453                 vk::VK_QUEUE_FAMILY_IGNORED,                    // srcQueueFamilyIndex
5454                 vk::VK_QUEUE_FAMILY_IGNORED,                    // destQueueFamilyIndex
5455                 buffer  ,                                                               // buffer
5456                 0u,                                                                             // offset
5457                 (vk::VkDeviceSize)BUFFER_SIZE                   // size
5458         };
5459         return barrier;
5460 }
5461
5462 void TexelBufferInstanceBuffers::populateSourceBuffer (const tcu::PixelBufferAccess& access)
5463 {
5464         DE_ASSERT(access.getHeight() == 1);
5465         DE_ASSERT(access.getDepth() == 1);
5466
5467         const deInt32 width = access.getWidth();
5468
5469         for (int x = 0; x < width; ++x)
5470         {
5471                 const int                       red             = 255 * x / width;                                                                                              //!< gradient from 0 -> max (detects large offset errors)
5472                 const int                       green   = ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0));   //!< 3-level M pattern (detects small offset errors)
5473                 const int                       blue    = 16 * (x % 16);                                                                                                //!< 16-long triangle wave
5474
5475                 DE_ASSERT(de::inRange(red, 0, 255));
5476                 DE_ASSERT(de::inRange(green, 0, 255));
5477                 DE_ASSERT(de::inRange(blue, 0, 255));
5478
5479                 access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0);
5480         }
5481 }
5482
5483 void TexelBufferInstanceBuffers::uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data)
5484 {
5485         deMemcpy(memory.getHostPtr(), data.getPtr(), data.size());
5486         flushMappedMemoryRange(vki, device, memory.getMemory(), memory.getOffset(), data.size());
5487 }
5488
5489 int TexelBufferInstanceBuffers::getFetchPos (int fetchPosNdx)
5490 {
5491         static const int fetchPositions[4] =
5492         {
5493                 SAMPLE_POINT_0,
5494                 SAMPLE_POINT_1,
5495                 SAMPLE_POINT_2,
5496                 SAMPLE_POINT_3,
5497         };
5498         return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx);
5499 }
5500
5501 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue (int fetchPosNdx) const
5502 {
5503         // source order is ABAB
5504         const tcu::ConstPixelBufferAccess&      texelSrcA       = m_sourceViewA;
5505         const tcu::ConstPixelBufferAccess&      texelSrcB       = (m_numTexelBuffers == 1) ? (m_sourceViewA) : (m_sourceViewB);
5506         const tcu::ConstPixelBufferAccess&      texelSrc        = ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB);
5507
5508         return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0);
5509 }
5510
5511 class TexelBufferRenderInstance : public SingleCmdRenderInstance
5512 {
5513 public:
5514                                                                                                         TexelBufferRenderInstance       (vkt::Context&                  context,
5515                                                                                                                                                                  bool                                   isPrimaryCmdBuf,
5516                                                                                                                                                                  vk::VkDescriptorType   descriptorType,
5517                                                                                                                                                                  vk::VkShaderStageFlags stageFlags,
5518                                                                                                                                                                  ShaderInputInterface   shaderInterface,
5519                                                                                                                                                                  bool                                   nonzeroViewOffset);
5520
5521 private:
5522         static vk::Move<vk::VkDescriptorSetLayout>              createDescriptorSetLayout       (const vk::DeviceInterface&     vki,
5523                                                                                                                                                                  vk::VkDevice                           device,
5524                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
5525                                                                                                                                                                  ShaderInputInterface           shaderInterface,
5526                                                                                                                                                                  vk::VkShaderStageFlags         stageFlags);
5527
5528         static vk::Move<vk::VkPipelineLayout>                   createPipelineLayout            (const vk::DeviceInterface&     vki,
5529                                                                                                                                                                  vk::VkDevice                           device,
5530                                                                                                                                                                  vk::VkDescriptorSetLayout      descriptorSetLayout);
5531
5532         static vk::Move<vk::VkDescriptorPool>                   createDescriptorPool            (const vk::DeviceInterface&     vki,
5533                                                                                                                                                                  vk::VkDevice                           device,
5534                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
5535                                                                                                                                                                  ShaderInputInterface           shaderInterface);
5536
5537         static vk::Move<vk::VkDescriptorSet>                    createDescriptorSet                     (const vk::DeviceInterface&     vki,
5538                                                                                                                                                                  vk::VkDevice                           device,
5539                                                                                                                                                                  vk::VkDescriptorType           descriptorType,
5540                                                                                                                                                                  ShaderInputInterface           shaderInterface,
5541                                                                                                                                                                  vk::VkDescriptorSetLayout      layout,
5542                                                                                                                                                                  vk::VkDescriptorPool           pool,
5543                                                                                                                                                                  vk::VkBufferView                       viewA,
5544                                                                                                                                                                  vk::VkBufferView                       viewB);
5545
5546         void                                                                                    logTestPlan                                     (void) const;
5547         vk::VkPipelineLayout                                                    getPipelineLayout                       (void) const;
5548         void                                                                                    writeDrawCmdBuffer                      (vk::VkCmdBuffer cmd) const;
5549         tcu::TestStatus                                                                 verifyResultImage                       (const tcu::ConstPixelBufferAccess& result) const;
5550
5551         enum
5552         {
5553                 RENDER_SIZE = 128,
5554         };
5555
5556         const vk::VkDescriptorType                                              m_descriptorType;
5557         const vk::VkShaderStageFlags                                    m_stageFlags;
5558         const ShaderInputInterface                                              m_shaderInterface;
5559         const bool                                                                              m_nonzeroViewOffset;
5560
5561         const vk::Unique<vk::VkDescriptorSetLayout>             m_descriptorSetLayout;
5562         const vk::Unique<vk::VkPipelineLayout>                  m_pipelineLayout;
5563         const TexelBufferInstanceBuffers                                m_texelBuffers;
5564         const vk::Unique<vk::VkDescriptorPool>                  m_descriptorPool;
5565         const vk::Unique<vk::VkDescriptorSet>                   m_descriptorSet;
5566 };
5567
5568 TexelBufferRenderInstance::TexelBufferRenderInstance (vkt::Context&                             context,
5569                                                                                                           bool                                          isPrimaryCmdBuf,
5570                                                                                                           vk::VkDescriptorType          descriptorType,
5571                                                                                                           vk::VkShaderStageFlags        stageFlags,
5572                                                                                                           ShaderInputInterface          shaderInterface,
5573                                                                                                           bool                                          nonzeroViewOffset)
5574         : SingleCmdRenderInstance       (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE))
5575         , m_descriptorType                      (descriptorType)
5576         , m_stageFlags                          (stageFlags)
5577         , m_shaderInterface                     (shaderInterface)
5578         , m_nonzeroViewOffset           (nonzeroViewOffset)
5579         , m_descriptorSetLayout         (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags))
5580         , m_pipelineLayout                      (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout))
5581         , m_texelBuffers                        (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
5582         , m_descriptorPool                      (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface))
5583         , m_descriptorSet                       (createDescriptorSet(m_vki, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_texelBuffers.getBufferViewA(), m_texelBuffers.getBufferViewB()))
5584 {
5585 }
5586
5587 vk::Move<vk::VkDescriptorSetLayout> TexelBufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface&    vki,
5588                                                                                                                                                                                   vk::VkDevice                                  device,
5589                                                                                                                                                                                   vk::VkDescriptorType                  descriptorType,
5590                                                                                                                                                                                   ShaderInputInterface                  shaderInterface,
5591                                                                                                                                                                                   vk::VkShaderStageFlags                stageFlags)
5592 {
5593         vk::DescriptorSetLayoutBuilder builder;
5594
5595         switch (shaderInterface)
5596         {
5597                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5598                         builder.addSingleBinding(descriptorType, stageFlags);
5599                         break;
5600
5601                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
5602                         builder.addSingleBinding(descriptorType, stageFlags);
5603                         builder.addSingleBinding(descriptorType, stageFlags);
5604                         break;
5605
5606                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5607                         builder.addArrayBinding(descriptorType, 2u, stageFlags);
5608                         break;
5609
5610                 default:
5611                         DE_FATAL("Impossible");
5612         }
5613
5614         return builder.build(vki, device);
5615 }
5616
5617 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout (const vk::DeviceInterface&      vki,
5618                                                                                                                                                                 vk::VkDevice                            device,
5619                                                                                                                                                                 vk::VkDescriptorSetLayout       descriptorSetLayout)
5620 {
5621         const vk::VkPipelineLayoutCreateInfo createInfo =
5622         {
5623                 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
5624                 DE_NULL,
5625                 1,                                              // descriptorSetCount
5626                 &descriptorSetLayout,   // pSetLayouts
5627                 0u,                                             // pushConstantRangeCount
5628                 DE_NULL,                                // pPushConstantRanges
5629         };
5630         return vk::createPipelineLayout(vki, device, &createInfo);
5631 }
5632
5633 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool (const vk::DeviceInterface&      vki,
5634                                                                                                                                                                 vk::VkDevice                                    device,
5635                                                                                                                                                                 vk::VkDescriptorType                    descriptorType,
5636                                                                                                                                                                 ShaderInputInterface                    shaderInterface)
5637 {
5638         return vk::DescriptorPoolBuilder()
5639                 .addType(descriptorType, getInterfaceNumResources(shaderInterface))
5640                 .build(vki, device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
5641 }
5642
5643 vk::Move<vk::VkDescriptorSet> TexelBufferRenderInstance::createDescriptorSet (const vk::DeviceInterface&        vki,
5644                                                                                                                                                           vk::VkDevice                                  device,
5645                                                                                                                                                           vk::VkDescriptorType                  descriptorType,
5646                                                                                                                                                           ShaderInputInterface                  shaderInterface,
5647                                                                                                                                                           vk::VkDescriptorSetLayout             layout,
5648                                                                                                                                                           vk::VkDescriptorPool                  pool,
5649                                                                                                                                                           vk::VkBufferView                              viewA,
5650                                                                                                                                                           vk::VkBufferView                              viewB)
5651 {
5652         const vk::VkDescriptorInfo              texelBufferInfos[2]     =
5653         {
5654                 createDescriptorInfo(viewA),
5655                 createDescriptorInfo(viewB),
5656         };
5657
5658         vk::Move<vk::VkDescriptorSet>   descriptorSet           = allocDescriptorSet(vki, device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
5659         vk::DescriptorSetUpdateBuilder  builder;
5660
5661         switch (shaderInterface)
5662         {
5663                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5664                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
5665                         break;
5666
5667                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
5668                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]);
5669                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &texelBufferInfos[1]);
5670                         break;
5671
5672                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5673                         builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, texelBufferInfos);
5674                         break;
5675
5676                 default:
5677                         DE_FATAL("Impossible");
5678         }
5679
5680         builder.update(vki, device);
5681         return descriptorSet;
5682 }
5683
5684 void TexelBufferRenderInstance::logTestPlan (void) const
5685 {
5686         std::ostringstream msg;
5687
5688         msg << "Rendering 2x2 grid.\n"
5689                 << "Single descriptor set. Descriptor set contains "
5690                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5691                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
5692                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5693                             (const char*)DE_NULL)
5694                 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5695                 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
5696                 << "Buffer format is " << vk::getFormatName(mapToVkTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
5697
5698         if (m_stageFlags == 0u)
5699         {
5700                 msg << "Descriptors are not accessed in any shader stage.\n";
5701         }
5702         else
5703         {
5704                 msg << "Color in each cell is fetched using the descriptor(s):\n";
5705
5706                 for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5707                 {
5708                         msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
5709
5710                         if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5711                         {
5712                                 const int srcResourceNdx = (resultNdx % 2); // ABAB source
5713                                 msg << " from texelBuffer " << srcResourceNdx;
5714                         }
5715
5716                         msg << "\n";
5717                 }
5718
5719                 msg << "Descriptors are accessed in {"
5720                         << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0)                      ? (" vertex")                   : (""))
5721                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_CONTROL_BIT) != 0)        ? (" tess_control")             : (""))
5722                         << (((m_stageFlags & vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT) != 0)     ? (" tess_evaluation")  : (""))
5723                         << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0)            ? (" geometry")                 : (""))
5724                         << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0)            ? (" fragment")                 : (""))
5725                         << " } stages.";
5726         }
5727
5728         m_context.getTestContext().getLog()
5729                 << tcu::TestLog::Message
5730                 << msg.str()
5731                 << tcu::TestLog::EndMessage;
5732 }
5733
5734 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout (void) const
5735 {
5736         return *m_pipelineLayout;
5737 }
5738
5739 void TexelBufferRenderInstance::writeDrawCmdBuffer (vk::VkCmdBuffer cmd) const
5740 {
5741         m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL);
5742         m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles)
5743 }
5744
5745 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const
5746 {
5747         const tcu::Vec4         green           (0.0f, 1.0f, 0.0f, 1.0f);
5748         const tcu::Vec4         yellow          (1.0f, 1.0f, 0.0f, 1.0f);
5749         const bool                      doFetch         = (m_stageFlags != 0u); // no active stages? Then don't fetch
5750         const tcu::Vec4         sample0         = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(0));
5751         const tcu::Vec4         sample1         = (!doFetch) ? (green)  : (m_texelBuffers.fetchTexelValue(1));
5752         const tcu::Vec4         sample2         = (!doFetch) ? (green)  : (m_texelBuffers.fetchTexelValue(2));
5753         const tcu::Vec4         sample3         = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(3));
5754         tcu::Surface            reference       (m_targetSize.x(), m_targetSize.y());
5755
5756         drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3);
5757
5758         if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT))
5759                 return tcu::TestStatus::fail("Image verification failed");
5760         else
5761                 return tcu::TestStatus::pass("Pass");
5762 }
5763
5764 class TexelBufferComputeInstance : public vkt::TestInstance
5765 {
5766 public:
5767                                                                                         TexelBufferComputeInstance      (vkt::Context&                  context,
5768                                                                                                                                                  vk::VkDescriptorType   descriptorType,
5769                                                                                                                                                  ShaderInputInterface   shaderInterface,
5770                                                                                                                                                  bool                                   nonzeroViewOffset);
5771
5772 private:
5773         vk::Move<vk::VkDescriptorSetLayout>             createDescriptorSetLayout       (void) const;
5774         vk::Move<vk::VkDescriptorPool>                  createDescriptorPool            (void) const;
5775         vk::Move<vk::VkDescriptorSet>                   createDescriptorSet                     (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const;
5776
5777         tcu::TestStatus                                                 iterate                                         (void);
5778         void                                                                    logTestPlan                                     (void) const;
5779         tcu::TestStatus                                                 testResourceAccess                      (void);
5780
5781         const vk::VkDescriptorType                              m_descriptorType;
5782         const ShaderInputInterface                              m_shaderInterface;
5783         const bool                                                              m_nonzeroViewOffset;
5784
5785         const vk::DeviceInterface&                              m_vki;
5786         const vk::VkDevice                                              m_device;
5787         const vk::VkQueue                                               m_queue;
5788         const deUint32                                                  m_queueFamilyIndex;
5789         vk::Allocator&                                                  m_allocator;
5790
5791         const ComputeInstanceResultBuffer               m_result;
5792         const TexelBufferInstanceBuffers                m_texelBuffers;
5793 };
5794
5795 TexelBufferComputeInstance::TexelBufferComputeInstance (Context&                                context,
5796                                                                                                                 vk::VkDescriptorType    descriptorType,
5797                                                                                                                 ShaderInputInterface    shaderInterface,
5798                                                                                                                 bool                                    nonzeroViewOffset)
5799         : vkt::TestInstance             (context)
5800         , m_descriptorType              (descriptorType)
5801         , m_shaderInterface             (shaderInterface)
5802         , m_nonzeroViewOffset   (nonzeroViewOffset)
5803         , m_vki                                 (context.getDeviceInterface())
5804         , m_device                              (context.getDevice())
5805         , m_queue                               (context.getUniversalQueue())
5806         , m_queueFamilyIndex    (context.getUniversalQueueFamilyIndex())
5807         , m_allocator                   (context.getDefaultAllocator())
5808         , m_result                              (m_vki, m_device, m_allocator)
5809         , m_texelBuffers                (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset)
5810 {
5811 }
5812
5813 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout (void) const
5814 {
5815         vk::DescriptorSetLayoutBuilder builder;
5816
5817         builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5818
5819         switch (m_shaderInterface)
5820         {
5821                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5822                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5823                         break;
5824
5825                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
5826                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5827                         builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5828                         break;
5829
5830                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5831                         builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT);
5832                         break;
5833
5834                 default:
5835                         DE_FATAL("Impossible");
5836         };
5837
5838         return builder.build(m_vki, m_device);
5839 }
5840
5841 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool (void) const
5842 {
5843         return vk::DescriptorPoolBuilder()
5844                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
5845                 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface))
5846                 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
5847 }
5848
5849 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) const
5850 {
5851         const vk::VkDescriptorInfo              resultInfo                      = createDescriptorInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
5852         const vk::VkDescriptorInfo              texelBufferInfos[2]     =
5853         {
5854                 createDescriptorInfo(m_texelBuffers.getBufferViewA()),
5855                 createDescriptorInfo(m_texelBuffers.getBufferViewB()),
5856         };
5857
5858         vk::Move<vk::VkDescriptorSet>   descriptorSet           = allocDescriptorSet(m_vki, m_device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
5859         vk::DescriptorSetUpdateBuilder  builder;
5860
5861         // result
5862         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
5863
5864         // texel buffers
5865         switch (m_shaderInterface)
5866         {
5867                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
5868                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
5869                         break;
5870
5871                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
5872                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]);
5873                         builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &texelBufferInfos[1]);
5874                         break;
5875
5876                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
5877                         builder.writeArray(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, texelBufferInfos);
5878                         break;
5879
5880                 default:
5881                         DE_FATAL("Impossible");
5882         }
5883
5884         builder.update(m_vki, m_device);
5885         return descriptorSet;
5886 }
5887
5888 tcu::TestStatus TexelBufferComputeInstance::iterate (void)
5889 {
5890         logTestPlan();
5891         return testResourceAccess();
5892 }
5893
5894 void TexelBufferComputeInstance::logTestPlan (void) const
5895 {
5896         std::ostringstream msg;
5897
5898         msg << "Fetching 4 values from image in compute shader.\n"
5899                 << "Single descriptor set. Descriptor set contains "
5900                         << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" :
5901                             (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS) ? "two" :
5902                             (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" :
5903                             (const char*)DE_NULL)
5904                 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n"
5905                 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n"
5906                 << "Buffer format is " << vk::getFormatName(mapToVkTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n";
5907
5908         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5909         {
5910                 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx);
5911
5912                 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR)
5913                 {
5914                         const int srcResourceNdx = (resultNdx % 2); // ABAB source
5915                         msg << " from texelBuffer " << srcResourceNdx;
5916                 }
5917
5918                 msg << "\n";
5919         }
5920
5921         m_context.getTestContext().getLog()
5922                 << tcu::TestLog::Message
5923                 << msg.str()
5924                 << tcu::TestLog::EndMessage;
5925 }
5926
5927 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess (void)
5928 {
5929         const vk::Unique<vk::VkDescriptorSetLayout>             descriptorSetLayout     (createDescriptorSetLayout());
5930         const vk::Unique<vk::VkDescriptorPool>                  descriptorPool          (createDescriptorPool());
5931         const vk::Unique<vk::VkDescriptorSet>                   descriptorSet           (createDescriptorSet(*descriptorPool, *descriptorSetLayout));
5932         const ComputePipeline                                                   pipeline                        (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get());
5933
5934         const vk::VkDescriptorSet                                               descriptorSets[]        = { *descriptorSet };
5935         const int                                                                               numDescriptorSets       = DE_LENGTH_OF_ARRAY(descriptorSets);
5936         const deUint32* const                                                   dynamicOffsets          = DE_NULL;
5937         const int                                                                               numDynamicOffsets       = 0;
5938         const void*     const                                                           preBarriers[]           = { m_texelBuffers.getBufferInitBarrierA(), m_texelBuffers.getBufferInitBarrierB() };
5939         const int                                                                               numPreBarriers          = m_texelBuffers.getNumTexelBuffers();
5940         const void* const                                                               postBarriers[]          = { m_result.getResultReadBarrier() };
5941         const int                                                                               numPostBarriers         = DE_LENGTH_OF_ARRAY(postBarriers);
5942
5943         const ComputeCommand                                                    compute                         (m_vki,
5944                                                                                                                                                  m_device,
5945                                                                                                                                                  pipeline.getPipeline(),
5946                                                                                                                                                  pipeline.getPipelineLayout(),
5947                                                                                                                                                  tcu::UVec3(4, 1, 1),
5948                                                                                                                                                  numDescriptorSets,     descriptorSets,
5949                                                                                                                                                  numDynamicOffsets,     dynamicOffsets,
5950                                                                                                                                                  numPreBarriers,        preBarriers,
5951                                                                                                                                                  numPostBarriers,       postBarriers);
5952
5953         tcu::Vec4                                                                               results[4];
5954         bool                                                                                    anyResultSet            = false;
5955         bool                                                                                    allResultsOk            = true;
5956
5957         compute.submitAndWait(m_queueFamilyIndex, m_queue);
5958         m_result.readResultContentsTo(&results);
5959
5960         // verify
5961         for (int resultNdx = 0; resultNdx < 4; ++resultNdx)
5962         {
5963                 const tcu::Vec4 result                          = results[resultNdx];
5964                 const tcu::Vec4 reference                       = m_texelBuffers.fetchTexelValue(resultNdx);
5965                 const tcu::Vec4 conversionThreshold     = tcu::Vec4(1.0f / 255.0f);
5966
5967                 if (result != tcu::Vec4(-1.0f))
5968                         anyResultSet = true;
5969
5970                 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold)))
5971                 {
5972                         allResultsOk = false;
5973
5974                         m_context.getTestContext().getLog()
5975                                 << tcu::TestLog::Message
5976                                 << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result
5977                                 << tcu::TestLog::EndMessage;
5978                 }
5979         }
5980
5981         // read back and verify
5982         if (allResultsOk)
5983                 return tcu::TestStatus::pass("Pass");
5984         else if (anyResultSet)
5985                 return tcu::TestStatus::fail("Invalid result values");
5986         else
5987         {
5988                 m_context.getTestContext().getLog()
5989                         << tcu::TestLog::Message
5990                         << "Result buffer was not written to."
5991                         << tcu::TestLog::EndMessage;
5992                 return tcu::TestStatus::fail("Result buffer was not written to");
5993         }
5994 }
5995
5996 class TexelBufferDescriptorCase : public QuadrantRendederCase
5997 {
5998 public:
5999         enum
6000         {
6001                 FLAG_VIEW_OFFSET = (1u << 1u),
6002         };
6003         // enum continues where resource flags ends
6004         DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST);
6005
6006                                                                 TexelBufferDescriptorCase       (tcu::TestContext&              testCtx,
6007                                                                                                                          const char*                    name,
6008                                                                                                                          const char*                    description,
6009                                                                                                                          bool                                   isPrimaryCmdBuf,
6010                                                                                                                          vk::VkDescriptorType   descriptorType,
6011                                                                                                                          vk::VkShaderStageFlags exitingStages,
6012                                                                                                                          vk::VkShaderStageFlags activeStages,
6013                                                                                                                          ShaderInputInterface   shaderInterface,
6014                                                                                                                          deUint32                               flags);
6015
6016 private:
6017         std::string                                     genExtensionDeclarations        (vk::VkShaderStage stage) const;
6018         std::string                                     genResourceDeclarations         (vk::VkShaderStage stage, int numUsedBindings) const;
6019         std::string                                     genResourceAccessSource         (vk::VkShaderStage stage) const;
6020         std::string                                     genNoAccessSource                       (void) const;
6021
6022         vkt::TestInstance*                      createInstance                          (vkt::Context& context) const;
6023
6024         const bool                                      m_isPrimaryCmdBuf;
6025         const vk::VkDescriptorType      m_descriptorType;
6026         const ShaderInputInterface      m_shaderInterface;
6027         const bool                                      m_nonzeroViewOffset;
6028 };
6029
6030 TexelBufferDescriptorCase::TexelBufferDescriptorCase (tcu::TestContext&                 testCtx,
6031                                                                                                           const char*                           name,
6032                                                                                                           const char*                           description,
6033                                                                                                           bool                                          isPrimaryCmdBuf,
6034                                                                                                           vk::VkDescriptorType          descriptorType,
6035                                                                                                           vk::VkShaderStageFlags        exitingStages,
6036                                                                                                           vk::VkShaderStageFlags        activeStages,
6037                                                                                                           ShaderInputInterface          shaderInterface,
6038                                                                                                           deUint32                                      flags)
6039         : QuadrantRendederCase  (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages)
6040         , m_isPrimaryCmdBuf             (isPrimaryCmdBuf)
6041         , m_descriptorType              (descriptorType)
6042         , m_shaderInterface             (shaderInterface)
6043         , m_nonzeroViewOffset   (((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u))
6044 {
6045 }
6046
6047 std::string TexelBufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStage stage) const
6048 {
6049         DE_UNREF(stage);
6050         return "#extension GL_EXT_texture_buffer : require\n";
6051 }
6052
6053 std::string TexelBufferDescriptorCase::genResourceDeclarations (vk::VkShaderStage stage, int numUsedBindings) const
6054 {
6055         DE_UNREF(stage);
6056
6057         const bool                      isUniform               = isUniformDescriptorType(m_descriptorType);
6058         const char* const       storageType             = (isUniform) ? ("samplerBuffer ") : ("readonly imageBuffer ");
6059         const char* const       formatQualifier = (isUniform) ? ("") : (", rgba8");
6060
6061         switch (m_shaderInterface)
6062         {
6063                 case SHADER_INPUT_SINGLE_DESCRIPTOR:
6064                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer;\n";
6065
6066                 case SHADER_INPUT_MULTIPLE_DESCRIPTORS:
6067                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferA;\n"
6068                                    "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferB;\n";
6069
6070                 case SHADER_INPUT_DESCRIPTOR_ARRAY:
6071                         return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer[2];\n";
6072
6073                 default:
6074                         DE_FATAL("Impossible");
6075                         return "";
6076         }
6077 }
6078
6079 std::string TexelBufferDescriptorCase::genResourceAccessSource (vk::VkShaderStage stage) const
6080 {
6081         DE_UNREF(stage);
6082
6083         const char* const       accessPostfixA  = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)         ? ("")
6084                                                                                 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS)      ? ("A")
6085                                                                                 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)          ? ("[0]")
6086                                                                                 : (DE_NULL);
6087         const char* const       accessPostfixB  = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR)         ? ("")
6088                                                                                 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DESCRIPTORS)      ? ("B")
6089                                                                                 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY)          ? ("[1]")
6090                                                                                 : (DE_NULL);
6091         const char* const       fetchFunc               = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad");
6092         std::ostringstream      buf;
6093
6094         buf << "        if (quadrant_id == 0)\n"
6095                 << "            result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n"
6096                 << "    else if (quadrant_id == 1)\n"
6097                 << "            result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n"
6098                 << "    else if (quadrant_id == 2)\n"
6099                 << "            result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n"
6100                 << "    else\n"
6101                 << "            result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n";
6102
6103         return buf.str();
6104 }
6105
6106 std::string TexelBufferDescriptorCase::genNoAccessSource (void) const
6107 {
6108         return "        if (quadrant_id == 1 || quadrant_id == 2)\n"
6109                         "               result_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
6110                         "       else\n"
6111                         "               result_color = vec4(1.0, 1.0, 0.0, 1.0);\n";
6112 }
6113
6114 vkt::TestInstance* TexelBufferDescriptorCase::createInstance (vkt::Context& context) const
6115 {
6116         if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)
6117         {
6118                 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass
6119                 return new TexelBufferComputeInstance(context, m_descriptorType, m_shaderInterface, m_nonzeroViewOffset);
6120         }
6121         else
6122                 return new TexelBufferRenderInstance(context, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_nonzeroViewOffset);
6123 }
6124
6125 void createShaderAccessImageTests (tcu::TestCaseGroup*          group,
6126                                                                    bool                                         isPrimaryCmdBuf,
6127                                                                    vk::VkDescriptorType         descriptorType,
6128                                                                    vk::VkShaderStageFlags       exitingStages,
6129                                                                    vk::VkShaderStageFlags       activeStages,
6130                                                                    ShaderInputInterface         dimension,
6131                                                                    deUint32                                     resourceFlags)
6132 {
6133         static const struct
6134         {
6135                 vk::VkImageViewType     viewType;
6136                 const char*                     name;
6137                 const char*                     description;
6138                 deUint32                        flags;
6139         } s_imageTypes[] =
6140         {
6141                 { vk::VK_IMAGE_VIEW_TYPE_1D,                    "1d",                                           "1D image view",                                                                0u                                                                              },
6142                 { vk::VK_IMAGE_VIEW_TYPE_1D,                    "1d_base_mip",                          "1D image subview with base mip level",                 ImageDescriptorCase::FLAG_BASE_MIP              },
6143                 { vk::VK_IMAGE_VIEW_TYPE_1D,                    "1d_base_slice",                        "1D image subview with base array slice",               ImageDescriptorCase::FLAG_BASE_SLICE    },
6144
6145                 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,              "1d_array",                                     "1D array image view",                                                  0u                                                                              },
6146                 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,              "1d_array_base_mip",            "1D array image subview with base mip level",   ImageDescriptorCase::FLAG_BASE_MIP              },
6147                 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY,              "1d_array_base_slice",          "1D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE    },
6148
6149                 { vk::VK_IMAGE_VIEW_TYPE_2D,                    "2d",                                           "2D image view",                                                                0u                                                                              },
6150                 { vk::VK_IMAGE_VIEW_TYPE_2D,                    "2d_base_mip",                          "2D image subview with base mip level",                 ImageDescriptorCase::FLAG_BASE_MIP              },
6151                 { vk::VK_IMAGE_VIEW_TYPE_2D,                    "2d_base_slice",                        "2D image subview with base array slice",               ImageDescriptorCase::FLAG_BASE_SLICE    },
6152
6153                 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,              "2d_array",                                     "2D array image view",                                                  0u                                                                              },
6154                 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,              "2d_array_base_mip",            "2D array image subview with base mip level",   ImageDescriptorCase::FLAG_BASE_MIP              },
6155                 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY,              "2d_array_base_slice",          "2D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE    },
6156
6157                 { vk::VK_IMAGE_VIEW_TYPE_3D,                    "3d",                                           "3D image view",                                                                0u                                                                              },
6158                 { vk::VK_IMAGE_VIEW_TYPE_3D,                    "3d_base_mip",                          "3D image subview with base mip level",                 ImageDescriptorCase::FLAG_BASE_MIP              },
6159                 // no 3d array textures
6160
6161                 { vk::VK_IMAGE_VIEW_TYPE_CUBE,                  "cube",                                         "Cube image view",                                                              0u                                                                              },
6162                 { vk::VK_IMAGE_VIEW_TYPE_CUBE,                  "cube_base_mip",                        "Cube image subview with base mip level",               ImageDescriptorCase::FLAG_BASE_MIP              },
6163                 { vk::VK_IMAGE_VIEW_TYPE_CUBE,                  "cube_base_slice",                      "Cube image subview with base array slice",             ImageDescriptorCase::FLAG_BASE_SLICE    },
6164
6165                 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,    "cube_array",                           "Cube image view",                                                              0u                                                                              },
6166                 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,    "cube_array_base_mip",          "Cube image subview with base mip level",               ImageDescriptorCase::FLAG_BASE_MIP              },
6167                 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,    "cube_array_base_slice",        "Cube image subview with base array slice",             ImageDescriptorCase::FLAG_BASE_SLICE    },
6168         };
6169
6170         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx)
6171         {
6172                 // never overlap
6173                 DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u);
6174
6175                 group->addChild(new ImageDescriptorCase(group->getTestContext(),
6176                                                                                                 s_imageTypes[ndx].name,
6177                                                                                                 s_imageTypes[ndx].description,
6178                                                                                                 isPrimaryCmdBuf,
6179                                                                                                 descriptorType,
6180                                                                                                 exitingStages,
6181                                                                                                 activeStages,
6182                                                                                                 dimension,
6183                                                                                                 s_imageTypes[ndx].viewType,
6184                                                                                                 s_imageTypes[ndx].flags | resourceFlags));
6185         }
6186 }
6187
6188 void createShaderAccessTexelBufferTests (tcu::TestCaseGroup*    group,
6189                                                                                  bool                                   isPrimaryCmdBuf,
6190                                                                                  vk::VkDescriptorType   descriptorType,
6191                                                                                  vk::VkShaderStageFlags exitingStages,
6192                                                                                  vk::VkShaderStageFlags activeStages,
6193                                                                                  ShaderInputInterface   dimension,
6194                                                                                  deUint32                               resourceFlags)
6195 {
6196         DE_ASSERT(resourceFlags == 0);
6197         DE_UNREF(resourceFlags);
6198
6199         static const struct
6200         {
6201                 const char*     name;
6202                 const char*     description;
6203                 deUint32        flags;
6204         } s_texelBufferTypes[] =
6205         {
6206                 { "offset_zero",                "View offset is zero",          0u                                                                                      },
6207                 { "offset_nonzero",             "View offset is non-zero",      TexelBufferDescriptorCase::FLAG_VIEW_OFFSET     },
6208         };
6209
6210         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx)
6211         {
6212                 group->addChild(new TexelBufferDescriptorCase(group->getTestContext(),
6213                                                                                                           s_texelBufferTypes[ndx].name,
6214                                                                                                           s_texelBufferTypes[ndx].description,
6215                                                                                                           isPrimaryCmdBuf,
6216                                                                                                           descriptorType,
6217                                                                                                           exitingStages,
6218                                                                                                           activeStages,
6219                                                                                                           dimension,
6220                                                                                                           s_texelBufferTypes[ndx].flags));
6221         }
6222 }
6223
6224 void createShaderAccessBufferTests (tcu::TestCaseGroup*         group,
6225                                                                         bool                                    isPrimaryCmdBuf,
6226                                                                         vk::VkDescriptorType    descriptorType,
6227                                                                         vk::VkShaderStageFlags  exitingStages,
6228                                                                         vk::VkShaderStageFlags  activeStages,
6229                                                                         ShaderInputInterface    dimension,
6230                                                                         deUint32                                resourceFlags)
6231 {
6232         DE_ASSERT(resourceFlags == 0u);
6233         DE_UNREF(resourceFlags);
6234
6235         static const struct
6236         {
6237                 const char*     name;
6238                 const char*     description;
6239                 bool            isForDynamicCases;
6240                 deUint32        flags;
6241         } s_bufferTypes[] =
6242         {
6243                 { "offset_view_zero",                                           "View offset is zero",                                                                          false,  0u                                                                                                                                                                                      },
6244                 { "offset_view_nonzero",                                        "View offset is non-zero",                                                                      false,  BufferDescriptorCase::FLAG_VIEW_OFFSET                                                                                                          },
6245
6246                 { "offset_view_zero_dynamic_zero",                      "View offset is zero, dynamic offset is zero",                          true,   BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO                                                                                          },
6247                 { "offset_view_zero_dynamic_nonzero",           "View offset is zero, dynamic offset is non-zero",                      true,   BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO                                                                                       },
6248                 { "offset_view_zero_dynamic_not_set",           "View offset is zero, dynamic offset is not supplied",          true,   0u                                                                                                                                                                                      },
6249                 // \note no case for offset_view_nonzero_dynamic_zero since it doesn't produce any additional coverage
6250                 { "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      },
6251                 { "offset_view_nonzero_dynamic_not_set",        "View offset is non-zero, dynamic offset is not supplied",      true,   BufferDescriptorCase::FLAG_VIEW_OFFSET                                                                                                          },
6252         };
6253
6254         const bool isDynamicCase = isDynamicDescriptorType(descriptorType);
6255
6256         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx)
6257         {
6258                 if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases)
6259                         group->addChild(new BufferDescriptorCase(group->getTestContext(),
6260                                                                                                          s_bufferTypes[ndx].name,
6261                                                                                                          s_bufferTypes[ndx].description,
6262                                                                                                          isPrimaryCmdBuf,
6263                                                                                                          descriptorType,
6264                                                                                                          exitingStages,
6265                                                                                                          activeStages,
6266                                                                                                          dimension,
6267                                                                                                          s_bufferTypes[ndx].flags));
6268         }
6269 }
6270
6271 } // anonymous
6272
6273 tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx)
6274 {
6275         static const struct
6276         {
6277                 const bool      isPrimary;
6278                 const char*     name;
6279                 const char*     description;
6280         } s_bindTypes[] =
6281         {
6282                 { true,         "primary_cmd_buf",      "Bind in primary command buffer"        },
6283                 { false,        "seconday_cmd_buf",     "Bind in secondary command buffer"      },
6284         };
6285         static const struct
6286         {
6287                 const vk::VkDescriptorType      descriptorType;
6288                 const char*                                     name;
6289                 const char*                                     description;
6290                 deUint32                                        flags;
6291         } s_descriptorTypes[] =
6292         {
6293                 { vk::VK_DESCRIPTOR_TYPE_SAMPLER,                                       "sampler_mutable",                                      "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler",                                      0u                                                              },
6294                 { vk::VK_DESCRIPTOR_TYPE_SAMPLER,                                       "sampler_immutable",                            "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler",                            RESOURCE_FLAG_IMMUTABLE_SAMPLER },
6295                 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,        "combined_image_sampler_mutable",       "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler",       0u                                                              },
6296                 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,        "combined_image_sampler_immutable",     "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler",     RESOURCE_FLAG_IMMUTABLE_SAMPLER },
6297                 { vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,                         "sampled_image",                                        "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE",                                                                     0u                                                              },
6298                 { vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,                         "storage_image",                                        "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE",                                                                     0u                                                              },
6299                 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,          "uniform_texel_buffer",                         "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER",                                                      0u                                                              },
6300                 { vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,          "storage_texel_buffer",                         "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER",                                                      0u                                                              },
6301                 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,                        "uniform_buffer",                                       "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER",                                                            0u                                                              },
6302                 { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                        "storage_buffer",                                       "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER",                                                            0u                                                              },
6303                 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,        "uniform_buffer_dynamic",                       "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC",                                            0u                                                              },
6304                 { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,        "storage_buffer_dynamic",                       "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC",                                            0u                                                              },
6305         };
6306         static const struct
6307         {
6308                 const char*                             name;
6309                 const char*                             description;
6310                 vk::VkShaderStageFlags  existingStages;                         //!< stages that exists
6311                 vk::VkShaderStageFlags  activeStages;                           //!< stages that access resource
6312                 bool                                    supportsSecondaryCmdBufs;
6313         } s_shaderStages[] =
6314         {
6315                 {
6316                         "no_access",
6317                         "No accessing stages",
6318                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6319                         0u,
6320                         true,
6321                 },
6322                 {
6323                         "vertex",
6324                         "Vertex stage",
6325                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6326                         vk::VK_SHADER_STAGE_VERTEX_BIT,
6327                         true,
6328                 },
6329                 {
6330                         "tess_ctrl",
6331                         "Tessellation control stage",
6332                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESS_CONTROL_BIT | vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6333                         vk::VK_SHADER_STAGE_TESS_CONTROL_BIT,
6334                         true,
6335                 },
6336                 {
6337                         "tess_eval",
6338                         "Tessellation evaluation stage",
6339                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESS_CONTROL_BIT | vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6340                         vk::VK_SHADER_STAGE_TESS_EVALUATION_BIT,
6341                         true,
6342                 },
6343                 {
6344                         "geometry",
6345                         "Geometry stage",
6346                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6347                         vk::VK_SHADER_STAGE_GEOMETRY_BIT,
6348                         true,
6349                 },
6350                 {
6351                         "fragment",
6352                         "Fragment stage",
6353                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6354                         vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6355                         true,
6356                 },
6357                 {
6358                         "compute",
6359                         "Compute stage",
6360                         vk::VK_SHADER_STAGE_COMPUTE_BIT,
6361                         vk::VK_SHADER_STAGE_COMPUTE_BIT,
6362                         false,
6363                 },
6364                 {
6365                         "vertex_fragment",
6366                         "Vertex and fragment stages",
6367                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6368                         vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT,
6369                         true,
6370                 },
6371         };
6372         static const struct
6373         {
6374                 ShaderInputInterface    dimension;
6375                 const char*                             name;
6376                 const char*                             description;
6377         } s_variableDimensions[] =
6378         {
6379                 { SHADER_INPUT_SINGLE_DESCRIPTOR,               "single_descriptor",    "Single descriptor"             },
6380                 { SHADER_INPUT_MULTIPLE_DESCRIPTORS,    "multiple_descriptors", "Multiple descriptors"  },
6381                 { SHADER_INPUT_DESCRIPTOR_ARRAY,                "descriptor_array",             "Descriptor array"              },
6382         };
6383
6384         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access", "Access resource via descriptor in a single descriptor set"));
6385
6386         // .primary_cmd_buf...
6387         for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx)
6388         {
6389                 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name, s_bindTypes[bindTypeNdx].description));
6390
6391                 // .sampler, .combined_image_sampler, other resource types ...
6392                 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx)
6393                 {
6394                         de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description));
6395
6396                         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx)
6397                         {
6398                                 if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs)
6399                                 {
6400                                         de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name, s_shaderStages[stageNdx].description));
6401
6402                                         for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions); ++dimensionNdx)
6403                                         {
6404                                                 de::MovePtr<tcu::TestCaseGroup> dimensionGroup(new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name, s_variableDimensions[dimensionNdx].description));
6405                                                 void                                                    (*createTestsFunc)(tcu::TestCaseGroup*          group,
6406                                                                                                                                                    bool                                         isPrimaryCmdBuf,
6407                                                                                                                                                    vk::VkDescriptorType         descriptorType,
6408                                                                                                                                                    vk::VkShaderStageFlags       existingStages,
6409                                                                                                                                                    vk::VkShaderStageFlags       activeStages,
6410                                                                                                                                                    ShaderInputInterface         dimension,
6411                                                                                                                                                    deUint32                                     resourceFlags);
6412
6413                                                 switch (s_descriptorTypes[descriptorNdx].descriptorType)
6414                                                 {
6415                                                         case vk::VK_DESCRIPTOR_TYPE_SAMPLER:
6416                                                         case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
6417                                                         case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
6418                                                         case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
6419                                                                 createTestsFunc = createShaderAccessImageTests;
6420                                                                 break;
6421
6422                                                         case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
6423                                                         case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
6424                                                                 createTestsFunc = createShaderAccessTexelBufferTests;
6425                                                                 break;
6426
6427                                                         case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
6428                                                         case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
6429                                                         case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
6430                                                         case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
6431                                                                 createTestsFunc = createShaderAccessBufferTests;
6432                                                                 break;
6433
6434                                                         default:
6435                                                                 createTestsFunc = DE_NULL;
6436                                                                 DE_FATAL("Impossible");
6437                                                 }
6438
6439                                                 if (createTestsFunc)
6440                                                 {
6441                                                         createTestsFunc(dimensionGroup.get(),
6442                                                                                         s_bindTypes[bindTypeNdx].isPrimary,
6443                                                                                         s_descriptorTypes[descriptorNdx].descriptorType,
6444                                                                                         s_shaderStages[stageNdx].existingStages,
6445                                                                                         s_shaderStages[stageNdx].activeStages,
6446                                                                                         s_variableDimensions[dimensionNdx].dimension,
6447                                                                                         s_descriptorTypes[descriptorNdx].flags);
6448                                                 }
6449                                                 else
6450                                                         DE_FATAL("Impossible");
6451
6452                                                 stageGroup->addChild(dimensionGroup.release());
6453                                         }
6454
6455                                         typeGroup->addChild(stageGroup.release());
6456                                 }
6457                         }
6458
6459                         bindGroup->addChild(typeGroup.release());
6460                 }
6461
6462                 group->addChild(bindGroup.release());
6463         }
6464
6465         return group.release();
6466 }
6467
6468 } // BindingModel
6469 } // vkt