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