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