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