dEQP-VK.renderpass: Set IMAGE_USAGE_TRANSFER_SRC_BIT when needed
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageLoadStoreTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Mobica Ltd.
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 included
16  * 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 Khronos,
20  * 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 Image load/store Tests
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktImageLoadStoreTests.hpp"
36 #include "vktTestCaseUtil.hpp"
37 #include "vktImageTestsUtil.hpp"
38 #include "vktImageTexture.hpp"
39
40 #include "vkDefs.hpp"
41 #include "vkRef.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vkPlatform.hpp"
44 #include "vkPrograms.hpp"
45 #include "vkMemUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vkQueryUtil.hpp"
48 #include "vkImageUtil.hpp"
49
50 #include "deUniquePtr.hpp"
51 #include "deStringUtil.hpp"
52
53 #include "tcuImageCompare.hpp"
54 #include "tcuTexture.hpp"
55 #include "tcuTextureUtil.hpp"
56 #include "tcuFloat.hpp"
57
58 #include <string>
59 #include <vector>
60
61 using namespace vk;
62
63 namespace vkt
64 {
65 namespace image
66 {
67 namespace
68 {
69
70 inline VkImageCreateInfo makeImageCreateInfo (const Texture& texture, const VkFormat format, const VkImageUsageFlags usage)
71 {
72         const VkImageCreateInfo imageParams =
73         {
74                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                                            // VkStructureType                      sType;
75                 DE_NULL,                                                                                                                                                        // const void*                          pNext;
76                 (isCube(texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u),       // VkImageCreateFlags           flags;
77                 mapImageType(texture.type()),                                                                                                           // VkImageType                          imageType;
78                 format,                                                                                                                                                         // VkFormat                                     format;
79                 makeExtent3D(texture.layerSize()),                                                                                                      // VkExtent3D                           extent;
80                 1u,                                                                                                                                                                     // deUint32                                     mipLevels;
81                 (deUint32)texture.numLayers(),                                                                                                          // deUint32                                     arrayLayers;
82                 VK_SAMPLE_COUNT_1_BIT,                                                                                                                          // VkSampleCountFlagBits        samples;
83                 VK_IMAGE_TILING_OPTIMAL,                                                                                                                        // VkImageTiling                        tiling;
84                 usage,                                                                                                                                                          // VkImageUsageFlags            usage;
85                 VK_SHARING_MODE_EXCLUSIVE,                                                                                                                      // VkSharingMode                        sharingMode;
86                 0u,                                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
87                 DE_NULL,                                                                                                                                                        // const deUint32*                      pQueueFamilyIndices;
88                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                                      // VkImageLayout                        initialLayout;
89         };
90         return imageParams;
91 }
92
93 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
94 {
95         return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
96 }
97
98 ImageType getImageTypeForSingleLayer (const ImageType imageType)
99 {
100         switch (imageType)
101         {
102                 case IMAGE_TYPE_1D:
103                 case IMAGE_TYPE_1D_ARRAY:
104                         return IMAGE_TYPE_1D;
105
106                 case IMAGE_TYPE_2D:
107                 case IMAGE_TYPE_2D_ARRAY:
108                 case IMAGE_TYPE_CUBE:
109                 case IMAGE_TYPE_CUBE_ARRAY:
110                         // A single layer for cube is a 2d face
111                         return IMAGE_TYPE_2D;
112
113                 case IMAGE_TYPE_3D:
114                         return IMAGE_TYPE_3D;
115
116                 case IMAGE_TYPE_BUFFER:
117                         return IMAGE_TYPE_BUFFER;
118
119                 default:
120                         DE_FATAL("Internal test error");
121                         return IMAGE_TYPE_LAST;
122         }
123 }
124
125 float computeStoreColorScale (const VkFormat format, const tcu::IVec3 imageSize)
126 {
127         const int maxImageDimension = de::max(imageSize.x(), de::max(imageSize.y(), imageSize.z()));
128         const float div = static_cast<float>(maxImageDimension - 1);
129
130         if (isUnormFormat(format))
131                 return 1.0f / div;
132         else if (isSnormFormat(format))
133                 return 2.0f / div;
134         else
135                 return 1.0f;
136 }
137
138 inline float computeStoreColorBias (const VkFormat format)
139 {
140         return isSnormFormat(format) ? -1.0f : 0.0f;
141 }
142
143 inline bool isIntegerFormat (const VkFormat format)
144 {
145         return isIntFormat(format) || isUintFormat(format);
146 }
147
148 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
149 {
150         switch (texture.type())
151         {
152                 case IMAGE_TYPE_1D:
153                 case IMAGE_TYPE_2D:
154                 case IMAGE_TYPE_BUFFER:
155                         // Not layered
156                         DE_ASSERT(layer == 0);
157                         return access;
158
159                 case IMAGE_TYPE_1D_ARRAY:
160                         return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
161
162                 case IMAGE_TYPE_2D_ARRAY:
163                 case IMAGE_TYPE_CUBE:
164                 case IMAGE_TYPE_CUBE_ARRAY:
165                 case IMAGE_TYPE_3D:                     // 3d texture is treated as if depth was the layers
166                         return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
167
168                 default:
169                         DE_FATAL("Internal test error");
170                         return tcu::ConstPixelBufferAccess();
171         }
172 }
173
174 std::string getFormatCaseName (const VkFormat format)
175 {
176         const std::string fullName = getFormatName(format);
177
178         DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
179
180         return de::toLower(fullName.substr(10));
181 }
182
183 //! \return true if all layers match in both pixel buffers
184 bool comparePixelBuffers (tcu::TestLog&                                         log,
185                                                   const Texture&                                        texture,
186                                                   const VkFormat                                        format,
187                                                   const tcu::ConstPixelBufferAccess     reference,
188                                                   const tcu::ConstPixelBufferAccess     result)
189 {
190         DE_ASSERT(reference.getFormat() == result.getFormat());
191         DE_ASSERT(reference.getSize() == result.getSize());
192
193         const bool intFormat = isIntegerFormat(format);
194         const bool is3d = (texture.type() == IMAGE_TYPE_3D);
195         const int numLayersOrSlices = (is3d ? texture.size().z() : texture.numLayers());
196         const int numCubeFaces = 6;
197
198         int passedLayers = 0;
199         for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
200         {
201                 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
202                 const std::string comparisonDesc = "Image Comparison, " +
203                         (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
204                         is3d                     ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx));
205
206                 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
207                 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
208
209                 bool ok = false;
210                 if (intFormat)
211                         ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
212                 else
213                         ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
214
215                 if (ok)
216                         ++passedLayers;
217         }
218         return passedLayers == numLayersOrSlices;
219 }
220
221 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
222 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
223 {
224         DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
225
226         for (int z = 0; z < access.getDepth(); ++z)
227         for (int y = 0; y < access.getHeight(); ++y)
228         for (int x = 0; x < access.getWidth(); ++x)
229         {
230                 const tcu::Vec4 color(access.getPixel(x, y, z));
231                 tcu::Vec4 newColor = color;
232
233                 for (int i = 0; i < 4; ++i)
234                 {
235                         const tcu::Float32 f(color[i]);
236                         if (f.isDenorm() || f.isInf() || f.isNaN())
237                                 newColor[i] = 0.0f;
238                 }
239
240                 if (newColor != color)
241                         access.setPixel(newColor, x, y, z);
242         }
243 }
244
245 //!< replace invalid pixels in the image (-128)
246 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
247 {
248         DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
249
250         for (int z = 0; z < access.getDepth(); ++z)
251         for (int y = 0; y < access.getHeight(); ++y)
252         for (int x = 0; x < access.getWidth(); ++x)
253         {
254                 const tcu::IVec4 color(access.getPixelInt(x, y, z));
255                 tcu::IVec4 newColor = color;
256         
257                 for (int i = 0; i < 4; ++i)
258                 {
259                         const deInt32 oldColor(color[i]);
260                         if (oldColor == -128) newColor[i] = -127;
261                 }
262         
263                 if (newColor != color)
264                 access.setPixel(newColor, x, y, z);
265         }
266 }
267
268 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
269 {
270         // Generate a reference image data using the storage format
271
272         tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
273         const tcu::PixelBufferAccess access = reference.getAccess();
274
275         const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
276         const float storeColorBias = computeStoreColorBias(imageFormat);
277
278         const bool intFormat = isIntegerFormat(imageFormat);
279         const int xMax = imageSize.x() - 1;
280         const int yMax = imageSize.y() - 1;
281
282         for (int z = 0; z < imageSize.z(); ++z)
283         for (int y = 0; y < imageSize.y(); ++y)
284         for (int x = 0; x < imageSize.x(); ++x)
285         {
286                 const tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
287
288                 if (intFormat)
289                         access.setPixel(color, x, y, z);
290                 else
291                         access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
292         }
293
294         // If the image is to be accessed as a float texture, get rid of invalid values
295
296         if (isFloatFormat(readFormat) && imageFormat != readFormat)
297                 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
298         if (isSnormFormat(readFormat) && imageFormat != readFormat)
299                 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
300
301         return reference;
302 }
303
304 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
305 {
306         return generateReferenceImage(imageSize, imageFormat, imageFormat);
307 }
308
309 void flipHorizontally (const tcu::PixelBufferAccess access)
310 {
311         const int xMax = access.getWidth() - 1;
312         const int halfWidth = access.getWidth() / 2;
313
314         if (isIntegerFormat(mapTextureFormat(access.getFormat())))
315                 for (int z = 0; z < access.getDepth(); z++)
316                 for (int y = 0; y < access.getHeight(); y++)
317                 for (int x = 0; x < halfWidth; x++)
318                 {
319                         const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
320                         access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
321                         access.setPixel(temp, x, y, z);
322                 }
323         else
324                 for (int z = 0; z < access.getDepth(); z++)
325                 for (int y = 0; y < access.getHeight(); y++)
326                 for (int x = 0; x < halfWidth; x++)
327                 {
328                         const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
329                         access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
330                         access.setPixel(temp, x, y, z);
331                 }
332 }
333
334 #if defined(DE_DEBUG)
335 inline bool colorScaleAndBiasAreValid (const VkFormat format, const float colorScale, const float colorBias)
336 {
337         // Only normalized (fixed-point) formats may have scale/bias
338         const bool integerOrFloatFormat = isIntFormat(format) || isUintFormat(format) || isFloatFormat(format);
339         return !integerOrFloatFormat || (colorScale == 1.0f && colorBias == 0.0f);
340 }
341 #endif
342
343 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
344 {
345         return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
346 }
347
348 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
349 {
350         const DeviceInterface& vk = context.getDeviceInterface();
351
352         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
353         const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
354                 VK_ACCESS_SHADER_WRITE_BIT, 0u,
355                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
356                 image, fullImageSubresourceRange);
357
358         const void* const barriers[] = { &shaderWriteBarrier };
359
360         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriers), barriers);
361 }
362
363 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
364 {
365         const DeviceInterface& vk = context.getDeviceInterface();
366
367         const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
368                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
369                 buffer, 0ull, bufferSizeBytes);
370
371         const void* const barriers[] = { &shaderWriteBarrier };
372
373         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriers), barriers);
374 }
375
376 //! Copy all layers of an image to a buffer.
377 void commandCopyImageToBuffer (Context&                                 context,
378                                                            const VkCommandBuffer        cmdBuffer,
379                                                            const VkImage                        image,
380                                                            const VkBuffer                       buffer,
381                                                            const VkDeviceSize           bufferSizeBytes,
382                                                            const Texture&                       texture)
383 {
384         const DeviceInterface& vk = context.getDeviceInterface();
385
386         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
387         const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
388                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
389                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
390                 image, fullImageSubresourceRange);
391
392         const void* const barriersBeforeCopy[] = { &prepareForTransferBarrier };
393
394         const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
395
396         const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
397                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
398                 buffer, 0ull, bufferSizeBytes);
399
400         const void* const barriersAfterCopy[] = { &copyBarrier };
401
402         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriersBeforeCopy), barriersBeforeCopy);
403         vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &copyRegion);
404         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriersAfterCopy), barriersAfterCopy);
405 }
406
407 //! Minimum chunk size is determined by the offset alignment requirements.
408 VkDeviceSize getOptimalUniformBufferChunkSize (Context& context, VkDeviceSize minimumRequiredChunkSizeBytes)
409 {
410         const VkPhysicalDeviceProperties properties = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
411         const VkDeviceSize alignment = properties.limits.minUniformBufferOffsetAlignment;
412
413         if (minimumRequiredChunkSizeBytes > alignment)
414                 return alignment + (minimumRequiredChunkSizeBytes / alignment) * alignment;
415         else
416                 return alignment;
417 }
418
419 class StoreTest : public TestCase
420 {
421 public:
422         enum TestFlags
423         {
424                 FLAG_SINGLE_LAYER_BIND = 0x1,   //!< Run the shader multiple times, each time binding a different layer.
425         };
426
427                                                         StoreTest                       (tcu::TestContext&      testCtx,
428                                                                                                  const std::string&     name,
429                                                                                                  const std::string&     description,
430                                                                                                  const Texture&         texture,
431                                                                                                  const VkFormat         format,
432                                                                                                  const TestFlags        flags = static_cast<TestFlags>(0));
433
434         void                                    initPrograms            (SourceCollections& programCollection) const;
435
436         TestInstance*                   createInstance          (Context&                       context) const;
437
438 private:
439         const Texture                   m_texture;
440         const VkFormat                  m_format;
441         const bool                              m_singleLayerBind;
442 };
443
444 StoreTest::StoreTest (tcu::TestContext&         testCtx,
445                                           const std::string&    name,
446                                           const std::string&    description,
447                                           const Texture&                texture,
448                                           const VkFormat                format,
449                                           const TestFlags               flags)
450         : TestCase                      (testCtx, name, description)
451         , m_texture                     (texture)
452         , m_format                      (format)
453         , m_singleLayerBind     ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
454 {
455         if (m_singleLayerBind)
456                 DE_ASSERT(m_texture.numLayers() > 1);
457 }
458
459 void StoreTest::initPrograms (SourceCollections& programCollection) const
460 {
461         const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
462         const float storeColorBias = computeStoreColorBias(m_format);
463         DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
464
465         const std::string xMax = de::toString(m_texture.size().x() - 1);
466         const std::string yMax = de::toString(m_texture.size().y() - 1);
467         const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
468         const std::string colorBaseExpr = signednessPrefix + "vec4("
469                 + "gx^gy^gz, "
470                 + "(" + xMax + "-gx)^gy^gz, "
471                 + "gx^(" + yMax + "-gy)^gz, "
472                 + "(" + xMax + "-gx)^(" + yMax + "-gy)^gz)";
473
474         const std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
475                                                                   + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
476
477         const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
478         const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
479
480         const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
481         const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
482         const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
483
484         std::ostringstream src;
485         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
486                 << "\n"
487                 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
488                 << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform highp " << imageTypeStr << " u_image;\n";
489
490         if (m_singleLayerBind)
491                 src << "layout (binding = 1) readonly uniform Constants {\n"
492                         << "    int u_layerNdx;\n"
493                         << "};\n";
494
495         src << "\n"
496                 << "void main (void)\n"
497                 << "{\n"
498                 << "    int gx = int(gl_GlobalInvocationID.x);\n"
499                 << "    int gy = int(gl_GlobalInvocationID.y);\n"
500                 << "    int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
501                 << "    imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
502                 << "}\n";
503
504         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
505 }
506
507 //! Generic test iteration algorithm for image tests
508 class BaseTestInstance : public TestInstance
509 {
510 public:
511                                                                         BaseTestInstance                                                (Context&               context,
512                                                                                                                                                          const Texture& texture,
513                                                                                                                                                          const VkFormat format,
514                                                                                                                                                          const bool             singleLayerBind);
515
516         tcu::TestStatus                 iterate                                                                 (void);
517
518         virtual                                                 ~BaseTestInstance                                               (void) {}
519
520 protected:
521         virtual VkDescriptorSetLayout   prepareDescriptors                                              (void) = 0;
522         virtual tcu::TestStatus                 verifyResult                                                    (void) = 0;
523
524         virtual void                                    commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer) = 0;
525         virtual void                                    commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer) = 0;
526         virtual void                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer) = 0;
527
528         virtual void                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
529                                                                                                                                                          const VkPipelineLayout pipelineLayout,
530                                                                                                                                                          const int                              layerNdx) = 0;
531
532         const Texture                                   m_texture;
533         const VkFormat                                  m_format;
534         const bool                                              m_singleLayerBind;
535 };
536
537 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool singleLayerBind)
538         : TestInstance          (context)
539         , m_texture                     (texture)
540         , m_format                      (format)
541         , m_singleLayerBind     (singleLayerBind)
542 {
543 }
544
545 tcu::TestStatus BaseTestInstance::iterate (void)
546 {
547         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
548         const VkDevice                  device                          = m_context.getDevice();
549         const VkQueue                   queue                           = m_context.getUniversalQueue();
550         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
551
552         const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
553
554         const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
555         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
556         const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
557
558         const Unique<VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
559         const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
560
561         beginCommandBuffer(vk, *cmdBuffer);
562
563         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
564         commandBeforeCompute(*cmdBuffer);
565
566         const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
567         const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
568         for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
569         {
570                 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
571
572                 if (layerNdx > 0)
573                         commandBetweenShaderInvocations(*cmdBuffer);
574
575                 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
576         }
577
578         commandAfterCompute(*cmdBuffer);
579
580         endCommandBuffer(vk, *cmdBuffer);
581
582         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
583
584         return verifyResult();
585 }
586
587 //! Base store test implementation
588 class StoreTestInstance : public BaseTestInstance
589 {
590 public:
591                                                                         StoreTestInstance                                               (Context&               context,
592                                                                                                                                                          const Texture& texture,
593                                                                                                                                                          const VkFormat format,
594                                                                                                                                                          const bool             singleLayerBind);
595
596 protected:
597         tcu::TestStatus                                 verifyResult                                                    (void);
598
599         // Add empty implementations for functions that might be not needed
600         void                                                    commandBeforeCompute                                    (const VkCommandBuffer) {}
601         void                                                    commandBetweenShaderInvocations                 (const VkCommandBuffer) {}
602         void                                                    commandAfterCompute                                             (const VkCommandBuffer) {}
603
604         de::MovePtr<Buffer>                             m_imageBuffer;
605         const VkDeviceSize                              m_imageSizeBytes;
606 };
607
608 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool singleLayerBind)
609         : BaseTestInstance              (context, texture, format, singleLayerBind)
610         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
611 {
612         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
613         const VkDevice                  device          = m_context.getDevice();
614         Allocator&                              allocator       = m_context.getDefaultAllocator();
615
616         // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
617
618         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
619                 vk, device, allocator,
620                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
621                 MemoryRequirement::HostVisible));
622 }
623
624 tcu::TestStatus StoreTestInstance::verifyResult (void)
625 {
626         const DeviceInterface&  vk              = m_context.getDeviceInterface();
627         const VkDevice                  device  = m_context.getDevice();
628
629         const tcu::IVec3 imageSize = m_texture.size();
630         const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
631
632         const Allocation& alloc = m_imageBuffer->getAllocation();
633         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
634         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, alloc.getHostPtr());
635
636         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
637                 return tcu::TestStatus::pass("Passed");
638         else
639                 return tcu::TestStatus::fail("Image comparison failed");
640 }
641
642 //! Store test for images
643 class ImageStoreTestInstance : public StoreTestInstance
644 {
645 public:
646                                                                                 ImageStoreTestInstance                                  (Context&                               context,
647                                                                                                                                                                  const Texture&                 texture,
648                                                                                                                                                                  const VkFormat                 format,
649                                                                                                                                                                  const bool                             singleLayerBind);
650
651 protected:
652         VkDescriptorSetLayout                           prepareDescriptors                                              (void);
653         void                                                            commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer);
654         void                                                            commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer);
655         void                                                            commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
656
657         void                                                            commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
658                                                                                                                                                                  const VkPipelineLayout pipelineLayout,
659                                                                                                                                                                  const int                              layerNdx);
660
661         de::MovePtr<Image>                                      m_image;
662         de::MovePtr<Buffer>                                     m_constantsBuffer;
663         const VkDeviceSize                                      m_constantsBufferChunkSizeBytes;
664         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
665         Move<VkDescriptorPool>                          m_descriptorPool;
666         DynArray<Move<VkDescriptorSet> >        m_allDescriptorSets;
667         DynArray<Move<VkImageView> >            m_allImageViews;
668 };
669
670 ImageStoreTestInstance::ImageStoreTestInstance (Context&                context,
671                                                                                                 const Texture&  texture,
672                                                                                                 const VkFormat  format,
673                                                                                                 const bool              singleLayerBind)
674         : StoreTestInstance                                     (context, texture, format, singleLayerBind)
675         , m_constantsBufferChunkSizeBytes       (getOptimalUniformBufferChunkSize(context, sizeof(deUint32)))
676         , m_allDescriptorSets                           (texture.numLayers())
677         , m_allImageViews                                       (texture.numLayers())
678 {
679         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
680         const VkDevice                  device                          = m_context.getDevice();
681         Allocator&                              allocator                       = m_context.getDefaultAllocator();
682
683         m_image = de::MovePtr<Image>(new Image(
684                 vk, device, allocator,
685                 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
686                 MemoryRequirement::Any));
687
688         // This buffer will be used to pass constants to the shader
689
690         const int numLayers = m_texture.numLayers();
691         const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
692         m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
693                 vk, device, allocator,
694                 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
695                 MemoryRequirement::HostVisible));
696
697         {
698                 const Allocation& alloc = m_constantsBuffer->getAllocation();
699                 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
700
701                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
702
703                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
704                 {
705                         deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
706                         *valuePtr = static_cast<deUint32>(layerNdx);
707                 }
708
709                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
710         }
711 }
712
713 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
714 {
715         const DeviceInterface&  vk              = m_context.getDeviceInterface();
716         const VkDevice                  device  = m_context.getDevice();
717
718         const int numLayers = m_texture.numLayers();
719         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
720                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
721                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
722                 .build(vk, device);
723
724         m_descriptorPool = DescriptorPoolBuilder()
725                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
726                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
727                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
728
729         if (m_singleLayerBind)
730         {
731                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
732                 {
733                         m_allDescriptorSets[layerNdx] = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
734                         m_allImageViews[layerNdx] = makeImageView(vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
735                                                                                                           makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u));
736                 }
737         }
738         else // bind all layers at once
739         {
740                 m_allDescriptorSets[0] = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
741                 m_allImageViews[0] = makeImageView(vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
742                                                                                    makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers));
743         }
744
745         return *m_descriptorSetLayout;  // not passing the ownership
746 }
747
748 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
749 {
750         const DeviceInterface&  vk              = m_context.getDeviceInterface();
751         const VkDevice                  device  = m_context.getDevice();
752
753         const VkDescriptorSet descriptorSet = *m_allDescriptorSets[layerNdx];
754         const VkImageView imageView = *m_allImageViews[layerNdx];
755
756         const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
757
758         // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
759         const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
760                 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
761
762         DescriptorSetUpdateBuilder()
763                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
764                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
765                 .update(vk, device);
766         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
767 }
768
769 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
770 {
771         const DeviceInterface& vk = m_context.getDeviceInterface();
772
773         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
774         const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
775                 0u, 0u,
776                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
777                 m_image->get(), fullImageSubresourceRange);
778
779         const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
780         const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
781                 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
782                 m_constantsBuffer->get(), 0ull, constantsBufferSize);
783
784         const void* const barriersBefore[] = { &writeConstantsBarrier, &setImageLayoutBarrier };
785
786         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriersBefore), barriersBefore);
787 }
788
789 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
790 {
791         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
792 }
793
794 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
795 {
796         commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
797 }
798
799 //! Store test for buffers
800 class BufferStoreTestInstance : public StoreTestInstance
801 {
802 public:
803                                                                         BufferStoreTestInstance                                 (Context&                               context,
804                                                                                                                                                          const Texture&                 texture,
805                                                                                                                                                          const VkFormat                 format);
806
807 protected:
808         VkDescriptorSetLayout                   prepareDescriptors                                              (void);
809         void                                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
810
811         void                                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
812                                                                                                                                                          const VkPipelineLayout pipelineLayout,
813                                                                                                                                                          const int                              layerNdx);
814
815         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
816         Move<VkDescriptorPool>                  m_descriptorPool;
817         Move<VkDescriptorSet>                   m_descriptorSet;
818         Move<VkBufferView>                              m_bufferView;
819 };
820
821 BufferStoreTestInstance::BufferStoreTestInstance (Context&                      context,
822                                                                                                   const Texture&        texture,
823                                                                                                   const VkFormat        format)
824         : StoreTestInstance(context, texture, format, false)
825 {
826 }
827
828 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
829 {
830         const DeviceInterface&  vk              = m_context.getDeviceInterface();
831         const VkDevice                  device  = m_context.getDevice();
832
833         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
834                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
835                 .build(vk, device);
836
837         m_descriptorPool = DescriptorPoolBuilder()
838                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
839                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
840
841         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
842         m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
843
844         return *m_descriptorSetLayout;  // not passing the ownership
845 }
846
847 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
848 {
849         DE_ASSERT(layerNdx == 0);
850         DE_UNREF(layerNdx);
851
852         const VkDevice                  device  = m_context.getDevice();
853         const DeviceInterface&  vk              = m_context.getDeviceInterface();
854
855         DescriptorSetUpdateBuilder()
856                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
857                 .update(vk, device);
858         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
859 }
860
861 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
862 {
863         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes);
864 }
865
866 class LoadStoreTest : public TestCase
867 {
868 public:
869         enum TestFlags
870         {
871                 FLAG_SINGLE_LAYER_BIND  = 1 << 0,       //!< Run the shader multiple times, each time binding a different layer.
872                 FLAG_RESTRICT_IMAGES    = 1 << 1,       //!< If given, images in the shader will be qualified with "restrict".
873         };
874
875                                                         LoadStoreTest                   (tcu::TestContext&              testCtx,
876                                                                                                          const std::string&             name,
877                                                                                                          const std::string&             description,
878                                                                                                          const Texture&                 texture,
879                                                                                                          const VkFormat                 format,
880                                                                                                          const VkFormat                 imageFormat,
881                                                                                                          const TestFlags                flags = static_cast<TestFlags>(0));
882
883         void                                    initPrograms                    (SourceCollections&             programCollection) const;
884         TestInstance*                   createInstance                  (Context&                               context) const;
885
886 private:
887         const Texture                   m_texture;
888         const VkFormat                  m_format;                               //!< Format as accessed in the shader
889         const VkFormat                  m_imageFormat;                  //!< Storage format
890         const bool                              m_singleLayerBind;
891         const bool                              m_restrictImages;
892 };
893
894 LoadStoreTest::LoadStoreTest (tcu::TestContext&         testCtx,
895                                                           const std::string&    name,
896                                                           const std::string&    description,
897                                                           const Texture&                texture,
898                                                           const VkFormat                format,
899                                                           const VkFormat                imageFormat,
900                                                           const TestFlags               flags)
901         : TestCase                      (testCtx, name, description)
902         , m_texture                     (texture)
903         , m_format                      (format)
904         , m_imageFormat         (imageFormat)
905         , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
906         , m_restrictImages      ((flags & FLAG_RESTRICT_IMAGES) != 0)
907 {
908         if (m_singleLayerBind)
909                 DE_ASSERT(m_texture.numLayers() > 1);
910
911         DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
912 }
913
914 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
915 {
916         const int                       dimension                       = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
917         const ImageType         usedImageType           = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
918         const std::string       formatQualifierStr      = getShaderImageFormatQualifier(mapVkFormat(m_format));
919         const std::string       imageTypeStr            = getShaderImageType(mapVkFormat(m_format), usedImageType);
920         const std::string       maybeRestrictStr        = (m_restrictImages ? "restrict " : "");
921         const std::string       xMax                            = de::toString(m_texture.size().x() - 1);
922
923         std::ostringstream src;
924         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
925                 << "\n"
926                 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
927                 << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform highp " << imageTypeStr << " u_image0;\n"
928                 << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform highp " << imageTypeStr << " u_image1;\n"
929                 << "\n"
930                 << "void main (void)\n"
931                 << "{\n"
932                 << (dimension == 1 ?
933                         "    int pos = int(gl_GlobalInvocationID.x);\n"
934                         "    imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n"
935                         : dimension == 2 ?
936                         "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
937                         "    imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n"
938                         : dimension == 3 ?
939                         "    ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
940                         "    imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n"
941                         : "")
942                 << "}\n";
943
944         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
945 }
946
947 //! Load/store test base implementation
948 class LoadStoreTestInstance : public BaseTestInstance
949 {
950 public:
951                                                                         LoadStoreTestInstance                           (Context&                       context,
952                                                                                                                                                  const Texture&         texture,
953                                                                                                                                                  const VkFormat         format,
954                                                                                                                                                  const VkFormat         imageFormat,
955                                                                                                                                                  const bool                     singleLayerBind);
956
957 protected:
958         virtual Buffer*                                 getResultBuffer                                         (void) const = 0;       //!< Get the buffer that contains the result image
959
960         tcu::TestStatus                                 verifyResult                                            (void);
961
962         // Add empty implementations for functions that might be not needed
963         void                                                    commandBeforeCompute                            (const VkCommandBuffer) {}
964         void                                                    commandBetweenShaderInvocations         (const VkCommandBuffer) {}
965         void                                                    commandAfterCompute                                     (const VkCommandBuffer) {}
966
967         de::MovePtr<Buffer>                             m_imageBuffer;          //!< Source data and helper buffer
968         const VkDeviceSize                              m_imageSizeBytes;
969         const VkFormat                                  m_imageFormat;          //!< Image format (for storage, may be different than texture format)
970         tcu::TextureLevel                               m_referenceImage;       //!< Used as input data and later to verify result image
971 };
972
973 LoadStoreTestInstance::LoadStoreTestInstance (Context&                  context,
974                                                                                           const Texture&        texture,
975                                                                                           const VkFormat        format,
976                                                                                           const VkFormat        imageFormat,
977                                                                                           const bool            singleLayerBind)
978         : BaseTestInstance              (context, texture, format, singleLayerBind)
979         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
980         , m_imageFormat                 (imageFormat)
981         , m_referenceImage              (generateReferenceImage(texture.size(), imageFormat, format))
982 {
983         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
984         const VkDevice                  device          = m_context.getDevice();
985         Allocator&                              allocator       = m_context.getDefaultAllocator();
986
987         // A helper buffer with enough space to hold the whole image.
988
989         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
990                 vk, device, allocator,
991                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
992                 MemoryRequirement::HostVisible));
993
994         // Copy reference data to buffer for subsequent upload to image.
995
996         const Allocation& alloc = m_imageBuffer->getAllocation();
997         deMemcpy(alloc.getHostPtr(), m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
998         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
999 }
1000
1001 tcu::TestStatus LoadStoreTestInstance::verifyResult     (void)
1002 {
1003         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1004         const VkDevice                  device  = m_context.getDevice();
1005
1006         // Apply the same transformation as done in the shader
1007         const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1008         flipHorizontally(reference);
1009
1010         const Allocation& alloc = getResultBuffer()->getAllocation();
1011         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
1012         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), alloc.getHostPtr());
1013
1014         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1015                 return tcu::TestStatus::pass("Passed");
1016         else
1017                 return tcu::TestStatus::fail("Image comparison failed");
1018 }
1019
1020 //! Load/store test for images
1021 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1022 {
1023 public:
1024         struct PerLayerData
1025         {
1026                                                                                 PerLayerData            (Move<VkDescriptorSet>  descriptorSet,
1027                                                                                                                          Move<VkImageView>              imageViewSrc,
1028                                                                                                                          Move<VkImageView>              imageViewDst);
1029
1030                 const Unique<VkDescriptorSet>   descriptorSet;
1031                 const Unique<VkImageView>               imageViewSrc;
1032                 const Unique<VkImageView>               imageViewDst;
1033         };
1034
1035                                                                                         ImageLoadStoreTestInstance                      (Context&                               context,
1036                                                                                                                                                                  const Texture&                 texture,
1037                                                                                                                                                                  const VkFormat                 format,
1038                                                                                                                                                                  const VkFormat                 imageFormat,
1039                                                                                                                                                                  const bool                             singleLayerBind);
1040
1041 protected:
1042         VkDescriptorSetLayout                                   prepareDescriptors                                      (void);
1043         void                                                                    commandBeforeCompute                            (const VkCommandBuffer  cmdBuffer);
1044         void                                                                    commandBetweenShaderInvocations         (const VkCommandBuffer  cmdBuffer);
1045         void                                                                    commandAfterCompute                                     (const VkCommandBuffer  cmdBuffer);
1046
1047         void                                                                    commandBindDescriptorsForLayer          (const VkCommandBuffer  cmdBuffer,
1048                                                                                                                                                                  const VkPipelineLayout pipelineLayout,
1049                                                                                                                                                                  const int                              layerNdx);
1050
1051         Buffer*                                                                 getResultBuffer                                         (void) const { return m_imageBuffer.get(); }
1052
1053         de::MovePtr<Image>                                              m_imageSrc;
1054         de::MovePtr<Image>                                              m_imageDst;
1055         Move<VkDescriptorSetLayout>                             m_descriptorSetLayout;
1056         Move<VkDescriptorPool>                                  m_descriptorPool;
1057         DynArray<de::MovePtr<PerLayerData> >    m_perLayerData;
1058 };
1059
1060 ImageLoadStoreTestInstance::PerLayerData::PerLayerData (Move<VkDescriptorSet>   descriptorSet_,
1061                                                                                                                 Move<VkImageView>               imageViewSrc_,
1062                                                                                                                 Move<VkImageView>               imageViewDst_)
1063         : descriptorSet (descriptorSet_)
1064         , imageViewSrc  (imageViewSrc_)
1065         , imageViewDst  (imageViewDst_)
1066 {
1067 }
1068
1069 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context&                context,
1070                                                                                                                 const Texture&  texture,
1071                                                                                                                 const VkFormat  format,
1072                                                                                                                 const VkFormat  imageFormat,
1073                                                                                                                 const bool              singleLayerBind)
1074         : LoadStoreTestInstance (context, texture, format, imageFormat, singleLayerBind)
1075         , m_perLayerData                (texture.numLayers())
1076 {
1077         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
1078         const VkDevice                  device                          = m_context.getDevice();
1079         Allocator&                              allocator                       = m_context.getDefaultAllocator();
1080
1081         m_imageSrc = de::MovePtr<Image>(new Image(
1082                 vk, device, allocator,
1083                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT),
1084                 MemoryRequirement::Any));
1085
1086         m_imageDst = de::MovePtr<Image>(new Image(
1087                 vk, device, allocator,
1088                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
1089                 MemoryRequirement::Any));
1090 }
1091
1092 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1093 {
1094         const VkDevice                  device  = m_context.getDevice();
1095         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1096
1097         const int numLayers = m_texture.numLayers();
1098         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1099                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1100                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1101                 .build(vk, device);
1102
1103         m_descriptorPool = DescriptorPoolBuilder()
1104                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1105                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1106                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1107
1108         if (m_singleLayerBind)
1109         {
1110                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1111                 {
1112                         const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1113                         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1114
1115                         de::MovePtr<PerLayerData> data(new PerLayerData(
1116                                 makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout),
1117                                 makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange),
1118                                 makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange)));
1119
1120                         m_perLayerData[layerNdx] = data;
1121                 }
1122         }
1123         else // bind all layers at once
1124         {
1125                 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1126                 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1127
1128                 de::MovePtr<PerLayerData> data(new PerLayerData(
1129                         makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout),
1130                         makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange),
1131                         makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange)));
1132
1133                 m_perLayerData[0] = data;
1134         }
1135
1136         return *m_descriptorSetLayout;  // not passing the ownership
1137 }
1138
1139 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1140 {
1141         const VkDevice                  device  = m_context.getDevice();
1142         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1143
1144         const PerLayerData* data = m_perLayerData[layerNdx].get();
1145
1146         const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, *data->imageViewSrc, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1147         const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, *data->imageViewDst, VK_IMAGE_LAYOUT_GENERAL);
1148
1149         DescriptorSetUpdateBuilder()
1150                 .writeSingle(*data->descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1151                 .writeSingle(*data->descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1152                 .update(vk, device);
1153         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &data->descriptorSet.get(), 0u, DE_NULL);
1154 }
1155
1156 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1157 {
1158         const DeviceInterface& vk = m_context.getDeviceInterface();
1159
1160         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1161         {
1162                 const VkImageMemoryBarrier barrierSetSrcImageLayout = makeImageMemoryBarrier(
1163                         0u, 0u,
1164                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1165                         m_imageSrc->get(), fullImageSubresourceRange);
1166
1167                 const VkImageMemoryBarrier barrierSetDstImageLayout = makeImageMemoryBarrier(
1168                         0u, 0u,
1169                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1170                         m_imageDst->get(), fullImageSubresourceRange);
1171
1172                 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1173                         VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1174                         m_imageBuffer->get(), 0ull, m_imageSizeBytes);
1175
1176                 const void* const barriers[] = { &barrierSetSrcImageLayout, &barrierSetDstImageLayout, &barrierFlushHostWriteBeforeCopy };
1177
1178                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1179                         DE_FALSE, DE_LENGTH_OF_ARRAY(barriers), barriers);
1180         }
1181         {
1182                 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1183                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1184                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1185                         m_imageSrc->get(), fullImageSubresourceRange);
1186
1187                 const void* const barriers[] = { &barrierAfterCopy };
1188
1189                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1190
1191                 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1192                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, DE_FALSE, DE_LENGTH_OF_ARRAY(barriers), barriers);
1193         }
1194 }
1195
1196 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1197 {
1198         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1199 }
1200
1201 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1202 {
1203         commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1204 }
1205
1206 //! Load/store test for buffers
1207 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1208 {
1209 public:
1210                                                                         BufferLoadStoreTestInstance             (Context&                               context,
1211                                                                                                                                          const Texture&                 texture,
1212                                                                                                                                          const VkFormat                 format,
1213                                                                                                                                          const VkFormat                 imageFormat);
1214
1215 protected:
1216         VkDescriptorSetLayout                   prepareDescriptors                              (void);
1217         void                                                    commandAfterCompute                             (const VkCommandBuffer  cmdBuffer);
1218
1219         void                                                    commandBindDescriptorsForLayer  (const VkCommandBuffer  cmdBuffer,
1220                                                                                                                                          const VkPipelineLayout pipelineLayout,
1221                                                                                                                                          const int                              layerNdx);
1222
1223         Buffer*                                                 getResultBuffer                                 (void) const { return m_imageBufferDst.get(); }
1224
1225         de::MovePtr<Buffer>                             m_imageBufferDst;
1226         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
1227         Move<VkDescriptorPool>                  m_descriptorPool;
1228         Move<VkDescriptorSet>                   m_descriptorSet;
1229         Move<VkBufferView>                              m_bufferViewSrc;
1230         Move<VkBufferView>                              m_bufferViewDst;
1231 };
1232
1233 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context&                      context,
1234                                                                                                                   const Texture&        texture,
1235                                                                                                                   const VkFormat        format,
1236                                                                                                                   const VkFormat        imageFormat)
1237         : LoadStoreTestInstance(context, texture, format, imageFormat, false)
1238 {
1239         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1240         const VkDevice                  device          = m_context.getDevice();
1241         Allocator&                              allocator       = m_context.getDefaultAllocator();
1242
1243         // Create a destination buffer.
1244
1245         m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1246                 vk, device, allocator,
1247                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1248                 MemoryRequirement::HostVisible));
1249 }
1250
1251 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1252 {
1253         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1254         const VkDevice                  device  = m_context.getDevice();
1255
1256         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1257                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1258                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1259                 .build(vk, device);
1260
1261         m_descriptorPool = DescriptorPoolBuilder()
1262                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1263                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1264                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1265
1266         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1267         m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
1268         m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), m_format, 0ull, m_imageSizeBytes);
1269
1270         return *m_descriptorSetLayout;  // not passing the ownership
1271 }
1272
1273 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1274 {
1275         DE_ASSERT(layerNdx == 0);
1276         DE_UNREF(layerNdx);
1277
1278         const VkDevice                  device  = m_context.getDevice();
1279         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1280
1281         DescriptorSetUpdateBuilder()
1282                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewSrc.get())
1283                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1284                 .update(vk, device);
1285         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1286 }
1287
1288 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1289 {
1290         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes);
1291 }
1292
1293 TestInstance* StoreTest::createInstance (Context& context) const
1294 {
1295         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1296                 return new BufferStoreTestInstance(context, m_texture, m_format);
1297         else
1298                 return new ImageStoreTestInstance(context, m_texture, m_format, m_singleLayerBind);
1299 }
1300
1301 TestInstance* LoadStoreTest::createInstance (Context& context) const
1302 {
1303         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1304                 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat);
1305         else
1306                 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_singleLayerBind);
1307 }
1308
1309 // TODO Which image/format combinations should be supported? Spec says it should be queried with vkGetPhysicalDeviceImageFormatProperties.
1310 //      What about buffer/format? (texel storage buffer) (use vkGetPhysicalDeviceFormatProperties ?)
1311
1312 static const Texture s_textures[] =
1313 {
1314         Texture(IMAGE_TYPE_1D,                  tcu::IVec3(64,  1,      1),     1),
1315         Texture(IMAGE_TYPE_1D_ARRAY,    tcu::IVec3(64,  1,      1),     8),
1316         Texture(IMAGE_TYPE_2D,                  tcu::IVec3(64,  64,     1),     1),
1317         Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(64,  64,     1),     8),
1318         Texture(IMAGE_TYPE_3D,                  tcu::IVec3(64,  64,     8),     1),
1319         Texture(IMAGE_TYPE_CUBE,                tcu::IVec3(64,  64,     1),     6),
1320         Texture(IMAGE_TYPE_CUBE_ARRAY,  tcu::IVec3(64,  64,     1),     2*6),
1321         Texture(IMAGE_TYPE_BUFFER,              tcu::IVec3(64,  1,      1),     1),
1322 };
1323
1324 const Texture& getTestTexture (const ImageType imageType)
1325 {
1326         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1327                 if (s_textures[textureNdx].type() == imageType)
1328                         return s_textures[textureNdx];
1329
1330         DE_FATAL("Internal error");
1331         return s_textures[0];
1332 }
1333
1334 static const VkFormat s_formats[] =
1335 {
1336         VK_FORMAT_R32G32B32A32_SFLOAT,
1337         VK_FORMAT_R16G16B16A16_SFLOAT,
1338         VK_FORMAT_R32_SFLOAT,
1339
1340         VK_FORMAT_R32G32B32A32_UINT,
1341         VK_FORMAT_R16G16B16A16_UINT,
1342         VK_FORMAT_R8G8B8A8_UINT,
1343         VK_FORMAT_R32_UINT,
1344
1345         VK_FORMAT_R32G32B32A32_SINT,
1346         VK_FORMAT_R16G16B16A16_SINT,
1347         VK_FORMAT_R8G8B8A8_SINT,
1348         VK_FORMAT_R32_SINT,
1349
1350         VK_FORMAT_R8G8B8A8_UNORM,
1351
1352         VK_FORMAT_R8G8B8A8_SNORM,
1353 };
1354
1355 } // anonymous ns
1356
1357 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
1358 {
1359         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
1360
1361         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1362         {
1363                 const Texture& texture = s_textures[textureNdx];
1364                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1365                 const bool isLayered = (texture.numLayers() > 1);
1366
1367                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1368                 {
1369                         groupByImageViewType->addChild(new StoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
1370
1371                         if (isLayered)
1372                                 groupByImageViewType->addChild(new StoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]) + "_single_layer", "",
1373                                                                                                 texture, s_formats[formatNdx], StoreTest::FLAG_SINGLE_LAYER_BIND));
1374                 }
1375                 testGroup->addChild(groupByImageViewType.release());
1376         }
1377
1378         return testGroup.release();
1379 }
1380
1381 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
1382 {
1383         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
1384
1385         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1386         {
1387                 const Texture& texture = s_textures[textureNdx];
1388                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1389                 const bool isLayered = (texture.numLayers() > 1);
1390
1391                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1392                 {
1393                         groupByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]), "",
1394                                                                                         texture, s_formats[formatNdx], s_formats[formatNdx]));
1395
1396                         if (isLayered)
1397                                 groupByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]) + "_single_layer", "",
1398                                                                                                 texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_SINGLE_LAYER_BIND));
1399                 }
1400                 testGroup->addChild(groupByImageViewType.release());
1401         }
1402
1403         return testGroup.release();
1404 }
1405
1406 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
1407 {
1408         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
1409
1410         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1411         {
1412                 const Texture& texture = s_textures[textureNdx];
1413                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1414
1415                 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1416                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1417                 {
1418                         //TODO Are all conversions valid or do we have to limit (or expand) somehow? Is it stated anywhere in the spec?
1419
1420                         const std::string caseName = getFormatCaseName(s_formats[imageFormatNdx]) + "_" + getFormatCaseName(s_formats[formatNdx]);
1421                         if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
1422                                 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
1423                 }
1424                 testGroup->addChild(groupByImageViewType.release());
1425         }
1426
1427         return testGroup.release();
1428 }
1429
1430 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
1431 {
1432         const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
1433         const Texture& texture = getTestTexture(imageType);
1434         return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES));
1435 }
1436
1437 } // image
1438 } // vkt