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