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