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