Merge branch 'jekstrand_renderpass_transfer_bit_fix' into 'master'
[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, const VkImageCreateFlags flags)
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) | flags,       // 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         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier);
359 }
360
361 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
362 {
363         const DeviceInterface& vk = context.getDeviceInterface();
364
365         const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
366                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
367                 buffer, 0ull, bufferSizeBytes);
368
369         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
370 }
371
372 //! Copy all layers of an image to a buffer.
373 void commandCopyImageToBuffer (Context&                                 context,
374                                                            const VkCommandBuffer        cmdBuffer,
375                                                            const VkImage                        image,
376                                                            const VkBuffer                       buffer,
377                                                            const VkDeviceSize           bufferSizeBytes,
378                                                            const Texture&                       texture)
379 {
380         const DeviceInterface& vk = context.getDeviceInterface();
381
382         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
383         const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
384                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
385                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
386                 image, fullImageSubresourceRange);
387
388         const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
389
390         const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
391                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
392                 buffer, 0ull, bufferSizeBytes);
393
394         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier);
395         vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &copyRegion);
396         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &copyBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
397 }
398
399 //! Minimum chunk size is determined by the offset alignment requirements.
400 VkDeviceSize getOptimalUniformBufferChunkSize (Context& context, VkDeviceSize minimumRequiredChunkSizeBytes)
401 {
402         const VkPhysicalDeviceProperties properties = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
403         const VkDeviceSize alignment = properties.limits.minUniformBufferOffsetAlignment;
404
405         if (minimumRequiredChunkSizeBytes > alignment)
406                 return alignment + (minimumRequiredChunkSizeBytes / alignment) * alignment;
407         else
408                 return alignment;
409 }
410
411 class StoreTest : public TestCase
412 {
413 public:
414         enum TestFlags
415         {
416                 FLAG_SINGLE_LAYER_BIND = 0x1,   //!< Run the shader multiple times, each time binding a different layer.
417         };
418
419                                                         StoreTest                       (tcu::TestContext&      testCtx,
420                                                                                                  const std::string&     name,
421                                                                                                  const std::string&     description,
422                                                                                                  const Texture&         texture,
423                                                                                                  const VkFormat         format,
424                                                                                                  const TestFlags        flags = static_cast<TestFlags>(0));
425
426         void                                    initPrograms            (SourceCollections& programCollection) const;
427
428         TestInstance*                   createInstance          (Context&                       context) const;
429
430 private:
431         const Texture                   m_texture;
432         const VkFormat                  m_format;
433         const bool                              m_singleLayerBind;
434 };
435
436 StoreTest::StoreTest (tcu::TestContext&         testCtx,
437                                           const std::string&    name,
438                                           const std::string&    description,
439                                           const Texture&                texture,
440                                           const VkFormat                format,
441                                           const TestFlags               flags)
442         : TestCase                      (testCtx, name, description)
443         , m_texture                     (texture)
444         , m_format                      (format)
445         , m_singleLayerBind     ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
446 {
447         if (m_singleLayerBind)
448                 DE_ASSERT(m_texture.numLayers() > 1);
449 }
450
451 void StoreTest::initPrograms (SourceCollections& programCollection) const
452 {
453         const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
454         const float storeColorBias = computeStoreColorBias(m_format);
455         DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
456
457         const std::string xMax = de::toString(m_texture.size().x() - 1);
458         const std::string yMax = de::toString(m_texture.size().y() - 1);
459         const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
460         const std::string colorBaseExpr = signednessPrefix + "vec4("
461                 + "gx^gy^gz, "
462                 + "(" + xMax + "-gx)^gy^gz, "
463                 + "gx^(" + yMax + "-gy)^gz, "
464                 + "(" + xMax + "-gx)^(" + yMax + "-gy)^gz)";
465
466         const std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
467                                                                   + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
468
469         const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
470         const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
471
472         const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
473         const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
474         const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
475
476         std::ostringstream src;
477         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
478                 << "\n"
479                 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
480                 << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform highp " << imageTypeStr << " u_image;\n";
481
482         if (m_singleLayerBind)
483                 src << "layout (binding = 1) readonly uniform Constants {\n"
484                         << "    int u_layerNdx;\n"
485                         << "};\n";
486
487         src << "\n"
488                 << "void main (void)\n"
489                 << "{\n"
490                 << "    int gx = int(gl_GlobalInvocationID.x);\n"
491                 << "    int gy = int(gl_GlobalInvocationID.y);\n"
492                 << "    int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
493                 << "    imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
494                 << "}\n";
495
496         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
497 }
498
499 //! Generic test iteration algorithm for image tests
500 class BaseTestInstance : public TestInstance
501 {
502 public:
503                                                                         BaseTestInstance                                                (Context&               context,
504                                                                                                                                                          const Texture& texture,
505                                                                                                                                                          const VkFormat format,
506                                                                                                                                                          const bool             singleLayerBind);
507
508         tcu::TestStatus                 iterate                                                                 (void);
509
510         virtual                                                 ~BaseTestInstance                                               (void) {}
511
512 protected:
513         virtual VkDescriptorSetLayout   prepareDescriptors                                              (void) = 0;
514         virtual tcu::TestStatus                 verifyResult                                                    (void) = 0;
515
516         virtual void                                    commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer) = 0;
517         virtual void                                    commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer) = 0;
518         virtual void                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer) = 0;
519
520         virtual void                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
521                                                                                                                                                          const VkPipelineLayout pipelineLayout,
522                                                                                                                                                          const int                              layerNdx) = 0;
523
524         const Texture                                   m_texture;
525         const VkFormat                                  m_format;
526         const bool                                              m_singleLayerBind;
527 };
528
529 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool singleLayerBind)
530         : TestInstance          (context)
531         , m_texture                     (texture)
532         , m_format                      (format)
533         , m_singleLayerBind     (singleLayerBind)
534 {
535 }
536
537 tcu::TestStatus BaseTestInstance::iterate (void)
538 {
539         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
540         const VkDevice                  device                          = m_context.getDevice();
541         const VkQueue                   queue                           = m_context.getUniversalQueue();
542         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
543
544         const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
545
546         const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
547         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
548         const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
549
550         const Unique<VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
551         const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
552
553         beginCommandBuffer(vk, *cmdBuffer);
554
555         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
556         commandBeforeCompute(*cmdBuffer);
557
558         const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
559         const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
560         for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
561         {
562                 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
563
564                 if (layerNdx > 0)
565                         commandBetweenShaderInvocations(*cmdBuffer);
566
567                 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
568         }
569
570         commandAfterCompute(*cmdBuffer);
571
572         endCommandBuffer(vk, *cmdBuffer);
573
574         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
575
576         return verifyResult();
577 }
578
579 //! Base store test implementation
580 class StoreTestInstance : public BaseTestInstance
581 {
582 public:
583                                                                         StoreTestInstance                                               (Context&               context,
584                                                                                                                                                          const Texture& texture,
585                                                                                                                                                          const VkFormat format,
586                                                                                                                                                          const bool             singleLayerBind);
587
588 protected:
589         tcu::TestStatus                                 verifyResult                                                    (void);
590
591         // Add empty implementations for functions that might be not needed
592         void                                                    commandBeforeCompute                                    (const VkCommandBuffer) {}
593         void                                                    commandBetweenShaderInvocations                 (const VkCommandBuffer) {}
594         void                                                    commandAfterCompute                                             (const VkCommandBuffer) {}
595
596         de::MovePtr<Buffer>                             m_imageBuffer;
597         const VkDeviceSize                              m_imageSizeBytes;
598 };
599
600 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool singleLayerBind)
601         : BaseTestInstance              (context, texture, format, singleLayerBind)
602         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
603 {
604         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
605         const VkDevice                  device          = m_context.getDevice();
606         Allocator&                              allocator       = m_context.getDefaultAllocator();
607
608         // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
609
610         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
611                 vk, device, allocator,
612                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
613                 MemoryRequirement::HostVisible));
614 }
615
616 tcu::TestStatus StoreTestInstance::verifyResult (void)
617 {
618         const DeviceInterface&  vk              = m_context.getDeviceInterface();
619         const VkDevice                  device  = m_context.getDevice();
620
621         const tcu::IVec3 imageSize = m_texture.size();
622         const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
623
624         const Allocation& alloc = m_imageBuffer->getAllocation();
625         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
626         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, alloc.getHostPtr());
627
628         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
629                 return tcu::TestStatus::pass("Passed");
630         else
631                 return tcu::TestStatus::fail("Image comparison failed");
632 }
633
634 //! Store test for images
635 class ImageStoreTestInstance : public StoreTestInstance
636 {
637 public:
638                                                                                 ImageStoreTestInstance                                  (Context&                               context,
639                                                                                                                                                                  const Texture&                 texture,
640                                                                                                                                                                  const VkFormat                 format,
641                                                                                                                                                                  const bool                             singleLayerBind);
642
643 protected:
644         VkDescriptorSetLayout                           prepareDescriptors                                              (void);
645         void                                                            commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer);
646         void                                                            commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer);
647         void                                                            commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
648
649         void                                                            commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
650                                                                                                                                                                  const VkPipelineLayout pipelineLayout,
651                                                                                                                                                                  const int                              layerNdx);
652
653         de::MovePtr<Image>                                      m_image;
654         de::MovePtr<Buffer>                                     m_constantsBuffer;
655         const VkDeviceSize                                      m_constantsBufferChunkSizeBytes;
656         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
657         Move<VkDescriptorPool>                          m_descriptorPool;
658         DynArray<Move<VkDescriptorSet> >        m_allDescriptorSets;
659         DynArray<Move<VkImageView> >            m_allImageViews;
660 };
661
662 ImageStoreTestInstance::ImageStoreTestInstance (Context&                context,
663                                                                                                 const Texture&  texture,
664                                                                                                 const VkFormat  format,
665                                                                                                 const bool              singleLayerBind)
666         : StoreTestInstance                                     (context, texture, format, singleLayerBind)
667         , m_constantsBufferChunkSizeBytes       (getOptimalUniformBufferChunkSize(context, sizeof(deUint32)))
668         , m_allDescriptorSets                           (texture.numLayers())
669         , m_allImageViews                                       (texture.numLayers())
670 {
671         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
672         const VkDevice                  device                          = m_context.getDevice();
673         Allocator&                              allocator                       = m_context.getDefaultAllocator();
674
675         m_image = de::MovePtr<Image>(new Image(
676                 vk, device, allocator,
677                 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
678                 MemoryRequirement::Any));
679
680         // This buffer will be used to pass constants to the shader
681
682         const int numLayers = m_texture.numLayers();
683         const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
684         m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
685                 vk, device, allocator,
686                 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
687                 MemoryRequirement::HostVisible));
688
689         {
690                 const Allocation& alloc = m_constantsBuffer->getAllocation();
691                 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
692
693                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
694
695                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
696                 {
697                         deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
698                         *valuePtr = static_cast<deUint32>(layerNdx);
699                 }
700
701                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
702         }
703 }
704
705 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
706 {
707         const DeviceInterface&  vk              = m_context.getDeviceInterface();
708         const VkDevice                  device  = m_context.getDevice();
709
710         const int numLayers = m_texture.numLayers();
711         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
712                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
713                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
714                 .build(vk, device);
715
716         m_descriptorPool = DescriptorPoolBuilder()
717                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
718                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
719                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
720
721         if (m_singleLayerBind)
722         {
723                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
724                 {
725                         m_allDescriptorSets[layerNdx] = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
726                         m_allImageViews[layerNdx] = makeImageView(vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
727                                                                                                           makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u));
728                 }
729         }
730         else // bind all layers at once
731         {
732                 m_allDescriptorSets[0] = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
733                 m_allImageViews[0] = makeImageView(vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
734                                                                                    makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers));
735         }
736
737         return *m_descriptorSetLayout;  // not passing the ownership
738 }
739
740 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
741 {
742         const DeviceInterface&  vk              = m_context.getDeviceInterface();
743         const VkDevice                  device  = m_context.getDevice();
744
745         const VkDescriptorSet descriptorSet = *m_allDescriptorSets[layerNdx];
746         const VkImageView imageView = *m_allImageViews[layerNdx];
747
748         const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
749
750         // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
751         const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
752                 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
753
754         DescriptorSetUpdateBuilder()
755                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
756                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
757                 .update(vk, device);
758         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
759 }
760
761 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
762 {
763         const DeviceInterface& vk = m_context.getDeviceInterface();
764
765         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
766         const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
767                 0u, 0u,
768                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
769                 m_image->get(), fullImageSubresourceRange);
770
771         const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
772         const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
773                 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
774                 m_constantsBuffer->get(), 0ull, constantsBufferSize);
775
776         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
777 }
778
779 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
780 {
781         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
782 }
783
784 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
785 {
786         commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
787 }
788
789 //! Store test for buffers
790 class BufferStoreTestInstance : public StoreTestInstance
791 {
792 public:
793                                                                         BufferStoreTestInstance                                 (Context&                               context,
794                                                                                                                                                          const Texture&                 texture,
795                                                                                                                                                          const VkFormat                 format);
796
797 protected:
798         VkDescriptorSetLayout                   prepareDescriptors                                              (void);
799         void                                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
800
801         void                                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
802                                                                                                                                                          const VkPipelineLayout pipelineLayout,
803                                                                                                                                                          const int                              layerNdx);
804
805         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
806         Move<VkDescriptorPool>                  m_descriptorPool;
807         Move<VkDescriptorSet>                   m_descriptorSet;
808         Move<VkBufferView>                              m_bufferView;
809 };
810
811 BufferStoreTestInstance::BufferStoreTestInstance (Context&                      context,
812                                                                                                   const Texture&        texture,
813                                                                                                   const VkFormat        format)
814         : StoreTestInstance(context, texture, format, false)
815 {
816 }
817
818 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
819 {
820         const DeviceInterface&  vk              = m_context.getDeviceInterface();
821         const VkDevice                  device  = m_context.getDevice();
822
823         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
824                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
825                 .build(vk, device);
826
827         m_descriptorPool = DescriptorPoolBuilder()
828                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
829                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
830
831         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
832         m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
833
834         return *m_descriptorSetLayout;  // not passing the ownership
835 }
836
837 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
838 {
839         DE_ASSERT(layerNdx == 0);
840         DE_UNREF(layerNdx);
841
842         const VkDevice                  device  = m_context.getDevice();
843         const DeviceInterface&  vk              = m_context.getDeviceInterface();
844
845         DescriptorSetUpdateBuilder()
846                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
847                 .update(vk, device);
848         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
849 }
850
851 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
852 {
853         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes);
854 }
855
856 class LoadStoreTest : public TestCase
857 {
858 public:
859         enum TestFlags
860         {
861                 FLAG_SINGLE_LAYER_BIND  = 1 << 0,       //!< Run the shader multiple times, each time binding a different layer.
862                 FLAG_RESTRICT_IMAGES    = 1 << 1,       //!< If given, images in the shader will be qualified with "restrict".
863         };
864
865                                                         LoadStoreTest                   (tcu::TestContext&              testCtx,
866                                                                                                          const std::string&             name,
867                                                                                                          const std::string&             description,
868                                                                                                          const Texture&                 texture,
869                                                                                                          const VkFormat                 format,
870                                                                                                          const VkFormat                 imageFormat,
871                                                                                                          const TestFlags                flags = static_cast<TestFlags>(0));
872
873         void                                    initPrograms                    (SourceCollections&             programCollection) const;
874         TestInstance*                   createInstance                  (Context&                               context) const;
875
876 private:
877         const Texture                   m_texture;
878         const VkFormat                  m_format;                               //!< Format as accessed in the shader
879         const VkFormat                  m_imageFormat;                  //!< Storage format
880         const bool                              m_singleLayerBind;
881         const bool                              m_restrictImages;
882 };
883
884 LoadStoreTest::LoadStoreTest (tcu::TestContext&         testCtx,
885                                                           const std::string&    name,
886                                                           const std::string&    description,
887                                                           const Texture&                texture,
888                                                           const VkFormat                format,
889                                                           const VkFormat                imageFormat,
890                                                           const TestFlags               flags)
891         : TestCase                      (testCtx, name, description)
892         , m_texture                     (texture)
893         , m_format                      (format)
894         , m_imageFormat         (imageFormat)
895         , m_singleLayerBind ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
896         , m_restrictImages      ((flags & FLAG_RESTRICT_IMAGES) != 0)
897 {
898         if (m_singleLayerBind)
899                 DE_ASSERT(m_texture.numLayers() > 1);
900
901         DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
902 }
903
904 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
905 {
906         const int                       dimension                       = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
907         const ImageType         usedImageType           = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
908         const std::string       formatQualifierStr      = getShaderImageFormatQualifier(mapVkFormat(m_format));
909         const std::string       imageTypeStr            = getShaderImageType(mapVkFormat(m_format), usedImageType);
910         const std::string       maybeRestrictStr        = (m_restrictImages ? "restrict " : "");
911         const std::string       xMax                            = de::toString(m_texture.size().x() - 1);
912
913         std::ostringstream src;
914         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
915                 << "\n"
916                 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
917                 << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform highp " << imageTypeStr << " u_image0;\n"
918                 << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform highp " << imageTypeStr << " u_image1;\n"
919                 << "\n"
920                 << "void main (void)\n"
921                 << "{\n"
922                 << (dimension == 1 ?
923                         "    int pos = int(gl_GlobalInvocationID.x);\n"
924                         "    imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n"
925                         : dimension == 2 ?
926                         "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
927                         "    imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n"
928                         : dimension == 3 ?
929                         "    ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
930                         "    imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n"
931                         : "")
932                 << "}\n";
933
934         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
935 }
936
937 //! Load/store test base implementation
938 class LoadStoreTestInstance : public BaseTestInstance
939 {
940 public:
941                                                                         LoadStoreTestInstance                           (Context&                       context,
942                                                                                                                                                  const Texture&         texture,
943                                                                                                                                                  const VkFormat         format,
944                                                                                                                                                  const VkFormat         imageFormat,
945                                                                                                                                                  const bool                     singleLayerBind);
946
947 protected:
948         virtual Buffer*                                 getResultBuffer                                         (void) const = 0;       //!< Get the buffer that contains the result image
949
950         tcu::TestStatus                                 verifyResult                                            (void);
951
952         // Add empty implementations for functions that might be not needed
953         void                                                    commandBeforeCompute                            (const VkCommandBuffer) {}
954         void                                                    commandBetweenShaderInvocations         (const VkCommandBuffer) {}
955         void                                                    commandAfterCompute                                     (const VkCommandBuffer) {}
956
957         de::MovePtr<Buffer>                             m_imageBuffer;          //!< Source data and helper buffer
958         const VkDeviceSize                              m_imageSizeBytes;
959         const VkFormat                                  m_imageFormat;          //!< Image format (for storage, may be different than texture format)
960         tcu::TextureLevel                               m_referenceImage;       //!< Used as input data and later to verify result image
961 };
962
963 LoadStoreTestInstance::LoadStoreTestInstance (Context&                  context,
964                                                                                           const Texture&        texture,
965                                                                                           const VkFormat        format,
966                                                                                           const VkFormat        imageFormat,
967                                                                                           const bool            singleLayerBind)
968         : BaseTestInstance              (context, texture, format, singleLayerBind)
969         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
970         , m_imageFormat                 (imageFormat)
971         , m_referenceImage              (generateReferenceImage(texture.size(), imageFormat, format))
972 {
973         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
974         const VkDevice                  device          = m_context.getDevice();
975         Allocator&                              allocator       = m_context.getDefaultAllocator();
976
977         // A helper buffer with enough space to hold the whole image.
978
979         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
980                 vk, device, allocator,
981                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
982                 MemoryRequirement::HostVisible));
983
984         // Copy reference data to buffer for subsequent upload to image.
985
986         const Allocation& alloc = m_imageBuffer->getAllocation();
987         deMemcpy(alloc.getHostPtr(), m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
988         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
989 }
990
991 tcu::TestStatus LoadStoreTestInstance::verifyResult     (void)
992 {
993         const DeviceInterface&  vk              = m_context.getDeviceInterface();
994         const VkDevice                  device  = m_context.getDevice();
995
996         // Apply the same transformation as done in the shader
997         const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
998         flipHorizontally(reference);
999
1000         const Allocation& alloc = getResultBuffer()->getAllocation();
1001         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
1002         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), alloc.getHostPtr());
1003
1004         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1005                 return tcu::TestStatus::pass("Passed");
1006         else
1007                 return tcu::TestStatus::fail("Image comparison failed");
1008 }
1009
1010 //! Load/store test for images
1011 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1012 {
1013 public:
1014         struct PerLayerData
1015         {
1016                                                                                 PerLayerData            (Move<VkDescriptorSet>  descriptorSet,
1017                                                                                                                          Move<VkImageView>              imageViewSrc,
1018                                                                                                                          Move<VkImageView>              imageViewDst);
1019
1020                 const Unique<VkDescriptorSet>   descriptorSet;
1021                 const Unique<VkImageView>               imageViewSrc;
1022                 const Unique<VkImageView>               imageViewDst;
1023         };
1024
1025                                                                                         ImageLoadStoreTestInstance                      (Context&                               context,
1026                                                                                                                                                                  const Texture&                 texture,
1027                                                                                                                                                                  const VkFormat                 format,
1028                                                                                                                                                                  const VkFormat                 imageFormat,
1029                                                                                                                                                                  const bool                             singleLayerBind);
1030
1031 protected:
1032         VkDescriptorSetLayout                                   prepareDescriptors                                      (void);
1033         void                                                                    commandBeforeCompute                            (const VkCommandBuffer  cmdBuffer);
1034         void                                                                    commandBetweenShaderInvocations         (const VkCommandBuffer  cmdBuffer);
1035         void                                                                    commandAfterCompute                                     (const VkCommandBuffer  cmdBuffer);
1036
1037         void                                                                    commandBindDescriptorsForLayer          (const VkCommandBuffer  cmdBuffer,
1038                                                                                                                                                                  const VkPipelineLayout pipelineLayout,
1039                                                                                                                                                                  const int                              layerNdx);
1040
1041         Buffer*                                                                 getResultBuffer                                         (void) const { return m_imageBuffer.get(); }
1042
1043         de::MovePtr<Image>                                              m_imageSrc;
1044         de::MovePtr<Image>                                              m_imageDst;
1045         Move<VkDescriptorSetLayout>                             m_descriptorSetLayout;
1046         Move<VkDescriptorPool>                                  m_descriptorPool;
1047         DynArray<de::MovePtr<PerLayerData> >    m_perLayerData;
1048 };
1049
1050 ImageLoadStoreTestInstance::PerLayerData::PerLayerData (Move<VkDescriptorSet>   descriptorSet_,
1051                                                                                                                 Move<VkImageView>               imageViewSrc_,
1052                                                                                                                 Move<VkImageView>               imageViewDst_)
1053         : descriptorSet (descriptorSet_)
1054         , imageViewSrc  (imageViewSrc_)
1055         , imageViewDst  (imageViewDst_)
1056 {
1057 }
1058
1059 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context&                context,
1060                                                                                                                 const Texture&  texture,
1061                                                                                                                 const VkFormat  format,
1062                                                                                                                 const VkFormat  imageFormat,
1063                                                                                                                 const bool              singleLayerBind)
1064         : LoadStoreTestInstance (context, texture, format, imageFormat, singleLayerBind)
1065         , m_perLayerData                (texture.numLayers())
1066 {
1067         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
1068         const VkDevice                          device                          = m_context.getDevice();
1069         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
1070         const VkImageCreateFlags        imageFlags                      = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1071
1072         m_imageSrc = de::MovePtr<Image>(new Image(
1073                 vk, device, allocator,
1074                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1075                 MemoryRequirement::Any));
1076
1077         m_imageDst = de::MovePtr<Image>(new Image(
1078                 vk, device, allocator,
1079                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1080                 MemoryRequirement::Any));
1081 }
1082
1083 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1084 {
1085         const VkDevice                  device  = m_context.getDevice();
1086         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1087
1088         const int numLayers = m_texture.numLayers();
1089         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1090                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1091                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1092                 .build(vk, device);
1093
1094         m_descriptorPool = DescriptorPoolBuilder()
1095                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1096                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1097                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1098
1099         if (m_singleLayerBind)
1100         {
1101                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1102                 {
1103                         const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1104                         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1105
1106                         de::MovePtr<PerLayerData> data(new PerLayerData(
1107                                 makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout),
1108                                 makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange),
1109                                 makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange)));
1110
1111                         m_perLayerData[layerNdx] = data;
1112                 }
1113         }
1114         else // bind all layers at once
1115         {
1116                 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1117                 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1118
1119                 de::MovePtr<PerLayerData> data(new PerLayerData(
1120                         makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout),
1121                         makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange),
1122                         makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange)));
1123
1124                 m_perLayerData[0] = data;
1125         }
1126
1127         return *m_descriptorSetLayout;  // not passing the ownership
1128 }
1129
1130 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1131 {
1132         const VkDevice                  device  = m_context.getDevice();
1133         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1134
1135         const PerLayerData* data = m_perLayerData[layerNdx].get();
1136
1137         const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, *data->imageViewSrc, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1138         const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, *data->imageViewDst, VK_IMAGE_LAYOUT_GENERAL);
1139
1140         DescriptorSetUpdateBuilder()
1141                 .writeSingle(*data->descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1142                 .writeSingle(*data->descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1143                 .update(vk, device);
1144         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &data->descriptorSet.get(), 0u, DE_NULL);
1145 }
1146
1147 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1148 {
1149         const DeviceInterface& vk = m_context.getDeviceInterface();
1150
1151         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1152         {
1153                 const VkImageMemoryBarrier preCopyImageBarriers[] =
1154                 {
1155                         makeImageMemoryBarrier(
1156                                 0u, 0u,
1157                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1158                                 m_imageSrc->get(), fullImageSubresourceRange),
1159                         makeImageMemoryBarrier(
1160                                 0u, 0u,
1161                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1162                                 m_imageDst->get(), fullImageSubresourceRange)
1163                 };
1164
1165                 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1166                         VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1167                         m_imageBuffer->get(), 0ull, m_imageSizeBytes);
1168
1169                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1170                         (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1171         }
1172         {
1173                 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1174                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1175                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1176                         m_imageSrc->get(), fullImageSubresourceRange);
1177
1178                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1179
1180                 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1181                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
1182         }
1183 }
1184
1185 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1186 {
1187         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1188 }
1189
1190 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1191 {
1192         commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1193 }
1194
1195 //! Load/store test for buffers
1196 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1197 {
1198 public:
1199                                                                         BufferLoadStoreTestInstance             (Context&                               context,
1200                                                                                                                                          const Texture&                 texture,
1201                                                                                                                                          const VkFormat                 format,
1202                                                                                                                                          const VkFormat                 imageFormat);
1203
1204 protected:
1205         VkDescriptorSetLayout                   prepareDescriptors                              (void);
1206         void                                                    commandAfterCompute                             (const VkCommandBuffer  cmdBuffer);
1207
1208         void                                                    commandBindDescriptorsForLayer  (const VkCommandBuffer  cmdBuffer,
1209                                                                                                                                          const VkPipelineLayout pipelineLayout,
1210                                                                                                                                          const int                              layerNdx);
1211
1212         Buffer*                                                 getResultBuffer                                 (void) const { return m_imageBufferDst.get(); }
1213
1214         de::MovePtr<Buffer>                             m_imageBufferDst;
1215         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
1216         Move<VkDescriptorPool>                  m_descriptorPool;
1217         Move<VkDescriptorSet>                   m_descriptorSet;
1218         Move<VkBufferView>                              m_bufferViewSrc;
1219         Move<VkBufferView>                              m_bufferViewDst;
1220 };
1221
1222 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context&                      context,
1223                                                                                                                   const Texture&        texture,
1224                                                                                                                   const VkFormat        format,
1225                                                                                                                   const VkFormat        imageFormat)
1226         : LoadStoreTestInstance(context, texture, format, imageFormat, false)
1227 {
1228         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1229         const VkDevice                  device          = m_context.getDevice();
1230         Allocator&                              allocator       = m_context.getDefaultAllocator();
1231
1232         // Create a destination buffer.
1233
1234         m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1235                 vk, device, allocator,
1236                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1237                 MemoryRequirement::HostVisible));
1238 }
1239
1240 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1241 {
1242         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1243         const VkDevice                  device  = m_context.getDevice();
1244
1245         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1246                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1247                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1248                 .build(vk, device);
1249
1250         m_descriptorPool = DescriptorPoolBuilder()
1251                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1252                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1253                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1254
1255         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1256         m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
1257         m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), m_format, 0ull, m_imageSizeBytes);
1258
1259         return *m_descriptorSetLayout;  // not passing the ownership
1260 }
1261
1262 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1263 {
1264         DE_ASSERT(layerNdx == 0);
1265         DE_UNREF(layerNdx);
1266
1267         const VkDevice                  device  = m_context.getDevice();
1268         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1269
1270         DescriptorSetUpdateBuilder()
1271                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewSrc.get())
1272                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1273                 .update(vk, device);
1274         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1275 }
1276
1277 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1278 {
1279         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes);
1280 }
1281
1282 TestInstance* StoreTest::createInstance (Context& context) const
1283 {
1284         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1285                 return new BufferStoreTestInstance(context, m_texture, m_format);
1286         else
1287                 return new ImageStoreTestInstance(context, m_texture, m_format, m_singleLayerBind);
1288 }
1289
1290 TestInstance* LoadStoreTest::createInstance (Context& context) const
1291 {
1292         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1293                 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat);
1294         else
1295                 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_singleLayerBind);
1296 }
1297
1298 // TODO Which image/format combinations should be supported? Spec says it should be queried with vkGetPhysicalDeviceImageFormatProperties.
1299 //      What about buffer/format? (texel storage buffer) (use vkGetPhysicalDeviceFormatProperties ?)
1300
1301 static const Texture s_textures[] =
1302 {
1303         Texture(IMAGE_TYPE_1D,                  tcu::IVec3(64,  1,      1),     1),
1304         Texture(IMAGE_TYPE_1D_ARRAY,    tcu::IVec3(64,  1,      1),     8),
1305         Texture(IMAGE_TYPE_2D,                  tcu::IVec3(64,  64,     1),     1),
1306         Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(64,  64,     1),     8),
1307         Texture(IMAGE_TYPE_3D,                  tcu::IVec3(64,  64,     8),     1),
1308         Texture(IMAGE_TYPE_CUBE,                tcu::IVec3(64,  64,     1),     6),
1309         Texture(IMAGE_TYPE_CUBE_ARRAY,  tcu::IVec3(64,  64,     1),     2*6),
1310         Texture(IMAGE_TYPE_BUFFER,              tcu::IVec3(64,  1,      1),     1),
1311 };
1312
1313 const Texture& getTestTexture (const ImageType imageType)
1314 {
1315         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1316                 if (s_textures[textureNdx].type() == imageType)
1317                         return s_textures[textureNdx];
1318
1319         DE_FATAL("Internal error");
1320         return s_textures[0];
1321 }
1322
1323 static const VkFormat s_formats[] =
1324 {
1325         VK_FORMAT_R32G32B32A32_SFLOAT,
1326         VK_FORMAT_R16G16B16A16_SFLOAT,
1327         VK_FORMAT_R32_SFLOAT,
1328
1329         VK_FORMAT_R32G32B32A32_UINT,
1330         VK_FORMAT_R16G16B16A16_UINT,
1331         VK_FORMAT_R8G8B8A8_UINT,
1332         VK_FORMAT_R32_UINT,
1333
1334         VK_FORMAT_R32G32B32A32_SINT,
1335         VK_FORMAT_R16G16B16A16_SINT,
1336         VK_FORMAT_R8G8B8A8_SINT,
1337         VK_FORMAT_R32_SINT,
1338
1339         VK_FORMAT_R8G8B8A8_UNORM,
1340
1341         VK_FORMAT_R8G8B8A8_SNORM,
1342 };
1343
1344 } // anonymous ns
1345
1346 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
1347 {
1348         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
1349
1350         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1351         {
1352                 const Texture& texture = s_textures[textureNdx];
1353                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1354                 const bool isLayered = (texture.numLayers() > 1);
1355
1356                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1357                 {
1358                         groupByImageViewType->addChild(new StoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
1359
1360                         if (isLayered)
1361                                 groupByImageViewType->addChild(new StoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]) + "_single_layer", "",
1362                                                                                                 texture, s_formats[formatNdx], StoreTest::FLAG_SINGLE_LAYER_BIND));
1363                 }
1364                 testGroup->addChild(groupByImageViewType.release());
1365         }
1366
1367         return testGroup.release();
1368 }
1369
1370 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
1371 {
1372         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
1373
1374         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1375         {
1376                 const Texture& texture = s_textures[textureNdx];
1377                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1378                 const bool isLayered = (texture.numLayers() > 1);
1379
1380                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1381                 {
1382                         groupByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]), "",
1383                                                                                         texture, s_formats[formatNdx], s_formats[formatNdx]));
1384
1385                         if (isLayered)
1386                                 groupByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatCaseName(s_formats[formatNdx]) + "_single_layer", "",
1387                                                                                                 texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_SINGLE_LAYER_BIND));
1388                 }
1389                 testGroup->addChild(groupByImageViewType.release());
1390         }
1391
1392         return testGroup.release();
1393 }
1394
1395 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
1396 {
1397         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
1398
1399         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1400         {
1401                 const Texture& texture = s_textures[textureNdx];
1402                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1403
1404                 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1405                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1406                 {
1407                         //TODO Are all conversions valid or do we have to limit (or expand) somehow? Is it stated anywhere in the spec?
1408
1409                         const std::string caseName = getFormatCaseName(s_formats[imageFormatNdx]) + "_" + getFormatCaseName(s_formats[formatNdx]);
1410                         if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
1411                                 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
1412                 }
1413                 testGroup->addChild(groupByImageViewType.release());
1414         }
1415
1416         return testGroup.release();
1417 }
1418
1419 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
1420 {
1421         const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
1422         const Texture& texture = getTestTexture(imageType);
1423         return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES));
1424 }
1425
1426 } // image
1427 } // vkt