Merge vk-gl-cts/vulkan-cts-1.2.7 into vk-gl-cts/vulkan-cts-1.2.8
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageLoadStoreTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Image load/store Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktImageLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "deMath.h"
45 #include "deUniquePtr.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deStringUtil.hpp"
48
49 #include "tcuImageCompare.hpp"
50 #include "tcuTexture.hpp"
51 #include "tcuTextureUtil.hpp"
52 #include "tcuFloat.hpp"
53 #include "tcuStringTemplate.hpp"
54 #include "tcuVectorUtil.hpp"
55
56 #include <string>
57 #include <vector>
58 #include <map>
59
60 using namespace vk;
61
62 namespace vkt
63 {
64 namespace image
65 {
66 namespace
67 {
68
69 // Check for three-component (non-packed) format, i.e. pixel size is a multiple of 3.
70 bool formatHasThreeComponents(VkFormat format)
71 {
72         const tcu::TextureFormat texFormat = mapVkFormat(format);
73         return (getPixelSize(texFormat) % 3) == 0;
74 }
75
76 VkFormat getSingleComponentFormat(VkFormat format)
77 {
78         tcu::TextureFormat texFormat = mapVkFormat(format);
79         texFormat = tcu::TextureFormat(tcu::TextureFormat::R, texFormat.type);
80         return mapTextureFormat(texFormat);
81 }
82
83 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
84 {
85         return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
86 }
87
88 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
89 {
90         switch (texture.type())
91         {
92                 case IMAGE_TYPE_1D:
93                 case IMAGE_TYPE_2D:
94                 case IMAGE_TYPE_BUFFER:
95                         // Not layered
96                         DE_ASSERT(layer == 0);
97                         return access;
98
99                 case IMAGE_TYPE_1D_ARRAY:
100                         return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
101
102                 case IMAGE_TYPE_2D_ARRAY:
103                 case IMAGE_TYPE_CUBE:
104                 case IMAGE_TYPE_CUBE_ARRAY:
105                 case IMAGE_TYPE_3D:                     // 3d texture is treated as if depth was the layers
106                         return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
107
108                 default:
109                         DE_FATAL("Internal test error");
110                         return tcu::ConstPixelBufferAccess();
111         }
112 }
113
114 //! \return the size in bytes of a given level of a mipmap image, including array layers.
115 vk::VkDeviceSize getMipmapLevelImageSizeBytes (const Texture& texture, const vk::VkFormat format, const deUint32 mipmapLevel)
116 {
117         tcu::IVec3 size = texture.size(mipmapLevel);
118         return tcu::getPixelSize(vk::mapVkFormat(format)) * size.x() * size.y() * size.z();
119 }
120
121 //! \return the size in bytes of the whole mipmap image, including all mipmap levels and array layers
122 vk::VkDeviceSize getMipmapImageTotalSizeBytes (const Texture& texture, const vk::VkFormat format)
123 {
124         vk::VkDeviceSize        size                    = 0u;
125         deInt32                         levelCount              = 0u;
126
127         do
128         {
129                 size += getMipmapLevelImageSizeBytes(texture, format, levelCount);
130                 levelCount++;
131         } while (levelCount < texture.numMipmapLevels());
132         return size;
133 }
134
135 //! \return true if all layers match in both pixel buffers
136 bool comparePixelBuffers (tcu::TestLog&                                         log,
137                                                   const Texture&                                        texture,
138                                                   const VkFormat                                        format,
139                                                   const tcu::ConstPixelBufferAccess     reference,
140                                                   const tcu::ConstPixelBufferAccess     result,
141                                                   const deUint32                                        mipmapLevel = 0u)
142 {
143         DE_ASSERT(reference.getFormat() == result.getFormat());
144         DE_ASSERT(reference.getSize() == result.getSize());
145
146         const bool is3d = (texture.type() == IMAGE_TYPE_3D);
147         const int numLayersOrSlices = (is3d ? texture.size(mipmapLevel).z() : texture.numLayers());
148         const int numCubeFaces = 6;
149
150         int passedLayers = 0;
151         for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
152         {
153                 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
154                 const std::string comparisonDesc = "Image Comparison, " +
155                         (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
156                         is3d                     ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx) + " , level " + de::toString(mipmapLevel));
157
158                 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
159                 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
160
161                 bool ok = false;
162
163                 switch (tcu::getTextureChannelClass(mapVkFormat(format).type))
164                 {
165                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
166                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
167                         {
168                                 ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
169                                 break;
170                         }
171
172                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
173                         {
174                                 // Allow error of minimum representable difference
175                                 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()) - 1u).cast<float>());
176
177                                 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
178                                 break;
179                         }
180
181                         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
182                         {
183                                 const tcu::UVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u;
184                                 // To avoid bit-shifting with negative value, which is undefined behaviour.
185                                 const tcu::UVec4 fixedBitDepth = tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u), tcu::greaterThanEqual(bitDepth.cast<deInt32>(), tcu::IVec4(0, 0, 0, 0)));
186
187                                 // Allow error of minimum representable difference
188                                 const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
189
190                                 ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
191                                 break;
192                         }
193
194                         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
195                         {
196                                 // Convert target format ulps to float ulps and allow 1 ulp difference
197                                 const tcu::UVec4 threshold (tcu::UVec4(1u) << (tcu::UVec4(23) - tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()));
198
199                                 ok = tcu::floatUlpThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
200                                 break;
201                         }
202
203                         default:
204                                 DE_FATAL("Unknown channel class");
205                 }
206
207                 if (ok)
208                         ++passedLayers;
209         }
210
211         return passedLayers == numLayersOrSlices;
212 }
213
214 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
215 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
216 {
217         DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
218
219         for (int z = 0; z < access.getDepth(); ++z)
220         for (int y = 0; y < access.getHeight(); ++y)
221         for (int x = 0; x < access.getWidth(); ++x)
222         {
223                 const tcu::Vec4 color(access.getPixel(x, y, z));
224                 tcu::Vec4 newColor = color;
225
226                 for (int i = 0; i < 4; ++i)
227                 {
228                         if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
229                         {
230                                 const tcu::Float16 f(color[i]);
231                                 if (f.isDenorm() || f.isInf() || f.isNaN())
232                                         newColor[i] = 0.0f;
233                         }
234                         else
235                         {
236                                 const tcu::Float32 f(color[i]);
237                                 if (f.isDenorm() || f.isInf() || f.isNaN())
238                                         newColor[i] = 0.0f;
239                         }
240                 }
241
242                 if (newColor != color)
243                         access.setPixel(newColor, x, y, z);
244         }
245 }
246
247 //!< replace invalid pixels in the image (-128)
248 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
249 {
250         DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
251
252         for (int z = 0; z < access.getDepth(); ++z)
253         for (int y = 0; y < access.getHeight(); ++y)
254         for (int x = 0; x < access.getWidth(); ++x)
255         {
256                 const tcu::IVec4 color(access.getPixelInt(x, y, z));
257                 tcu::IVec4 newColor = color;
258
259                 for (int i = 0; i < 4; ++i)
260                 {
261                         const deInt32 oldColor(color[i]);
262                         if (oldColor == -128) newColor[i] = -127;
263                 }
264
265                 if (newColor != color)
266                 access.setPixel(newColor, x, y, z);
267         }
268 }
269
270 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
271 {
272         // Generate a reference image data using the storage format
273
274         tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
275         const tcu::PixelBufferAccess access = reference.getAccess();
276
277         const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
278         const float storeColorBias = computeStoreColorBias(imageFormat);
279
280         const bool intFormat = isIntegerFormat(imageFormat);
281         const bool storeNegativeValues = isSignedFormat(imageFormat) && (storeColorBias == 0);
282         const int xMax = imageSize.x() - 1;
283         const int yMax = imageSize.y() - 1;
284
285         for (int z = 0; z < imageSize.z(); ++z)
286         for (int y = 0; y < imageSize.y(); ++y)
287         for (int x = 0; x < imageSize.x(); ++x)
288         {
289                 tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
290
291                 if (storeNegativeValues)
292                         color -= tcu::IVec4(deRoundFloatToInt32((float)de::max(xMax, yMax) / 2.0f));
293
294                 if (intFormat)
295                         access.setPixel(color, x, y, z);
296                 else
297                         access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
298         }
299
300         // If the image is to be accessed as a float texture, get rid of invalid values
301
302         if (isFloatFormat(readFormat) && imageFormat != readFormat)
303                 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
304         if (isSnormFormat(readFormat) && imageFormat != readFormat)
305                 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
306
307         return reference;
308 }
309
310 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
311 {
312         return generateReferenceImage(imageSize, imageFormat, imageFormat);
313 }
314
315 void flipHorizontally (const tcu::PixelBufferAccess access)
316 {
317         const int xMax = access.getWidth() - 1;
318         const int halfWidth = access.getWidth() / 2;
319
320         if (isIntegerFormat(mapTextureFormat(access.getFormat())))
321                 for (int z = 0; z < access.getDepth(); z++)
322                 for (int y = 0; y < access.getHeight(); y++)
323                 for (int x = 0; x < halfWidth; x++)
324                 {
325                         const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
326                         access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
327                         access.setPixel(temp, x, y, z);
328                 }
329         else
330                 for (int z = 0; z < access.getDepth(); z++)
331                 for (int y = 0; y < access.getHeight(); y++)
332                 for (int x = 0; x < halfWidth; x++)
333                 {
334                         const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
335                         access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
336                         access.setPixel(temp, x, y, z);
337                 }
338 }
339
340 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
341 {
342         return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
343 }
344
345 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
346 {
347         const DeviceInterface& vk = context.getDeviceInterface();
348
349         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
350         const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
351                 VK_ACCESS_SHADER_WRITE_BIT, 0u,
352                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
353                 image, fullImageSubresourceRange);
354
355         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);
356 }
357
358 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
359 {
360         const DeviceInterface& vk = context.getDeviceInterface();
361
362         const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
363                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
364                 buffer, 0ull, bufferSizeBytes);
365
366         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);
367 }
368
369 //! Copy all layers of an image to a buffer.
370 void commandCopyImageToBuffer (Context&                                 context,
371                                                            const VkCommandBuffer        cmdBuffer,
372                                                            const VkImage                        image,
373                                                            const VkBuffer                       buffer,
374                                                            const VkDeviceSize           bufferSizeBytes,
375                                                            const Texture&                       texture)
376 {
377         const DeviceInterface& vk = context.getDeviceInterface();
378
379         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
380         const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
381                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
382                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
383                 image, fullImageSubresourceRange);
384
385         const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
386
387         const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
388                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
389                 buffer, 0ull, bufferSizeBytes);
390
391         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);
392         vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &copyRegion);
393         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);
394 }
395
396 //! Copy all layers of a mipmap image to a buffer.
397 void commandCopyMipmapImageToBuffer (Context&                           context,
398                                                                          const VkCommandBuffer  cmdBuffer,
399                                                                          const VkImage                  image,
400                                                                          const VkFormat                 imageFormat,
401                                                                          const VkBuffer                 buffer,
402                                                                          const VkDeviceSize             bufferSizeBytes,
403                                                                          const Texture&                 texture)
404 {
405         const DeviceInterface& vk = context.getDeviceInterface();
406
407         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
408         const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
409                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
410                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
411                 image, fullImageSubresourceRange);
412
413         std::vector<VkBufferImageCopy> copyRegions;
414         VkDeviceSize bufferOffset = 0u;
415         for (deInt32 levelNdx = 0; levelNdx < texture.numMipmapLevels(); levelNdx++)
416         {
417                 const VkBufferImageCopy copyParams =
418                 {
419                         bufferOffset,                                                                                                                                                           //      VkDeviceSize                            bufferOffset;
420                         0u,                                                                                                                                                                                     //      deUint32                                        bufferRowLength;
421                         0u,                                                                                                                                                                                     //      deUint32                                        bufferImageHeight;
422                         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, texture.numLayers()),       //      VkImageSubresourceLayers        imageSubresource;
423                         makeOffset3D(0, 0, 0),                                                                                                                                          //      VkOffset3D                                      imageOffset;
424                         makeExtent3D(texture.layerSize(levelNdx)),                                                                                                      //      VkExtent3D                                      imageExtent;
425                 };
426                 copyRegions.push_back(copyParams);
427                 bufferOffset += getMipmapLevelImageSizeBytes(texture, imageFormat, levelNdx);
428         }
429
430         const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
431                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
432                 buffer, 0ull, bufferSizeBytes);
433
434         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);
435         vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, (deUint32) copyRegions.size(), copyRegions.data());
436         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);
437 }
438
439 class StoreTest : public TestCase
440 {
441 public:
442         enum TestFlags
443         {
444                 FLAG_SINGLE_LAYER_BIND                          = 0x1,  //!< Run the shader multiple times, each time binding a different layer.
445                 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER     = 0x2,  //!< Declare the format of the images in the shader code
446                 FLAG_MINALIGN                                           = 0x4,  //!< Use bufferview offset that matches the advertised minimum alignment
447         };
448
449                                                         StoreTest                       (tcu::TestContext&      testCtx,
450                                                                                                  const std::string&     name,
451                                                                                                  const std::string&     description,
452                                                                                                  const Texture&         texture,
453                                                                                                  const VkFormat         format,
454                                                                                                  const deUint32         flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
455
456         virtual void                    checkSupport            (Context&                       context) const;
457         void                                    initPrograms            (SourceCollections&     programCollection) const;
458         TestInstance*                   createInstance          (Context&                       context) const;
459
460 private:
461         const Texture                   m_texture;
462         const VkFormat                  m_format;
463         const bool                              m_declareImageFormatInShader;
464         const bool                              m_singleLayerBind;
465         const bool                              m_minalign;
466 };
467
468 StoreTest::StoreTest (tcu::TestContext&         testCtx,
469                                           const std::string&    name,
470                                           const std::string&    description,
471                                           const Texture&                texture,
472                                           const VkFormat                format,
473                                           const deUint32                flags)
474         : TestCase                                              (testCtx, name, description)
475         , m_texture                                             (texture)
476         , m_format                                              (format)
477         , m_declareImageFormatInShader  ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
478         , m_singleLayerBind                             ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
479         , m_minalign                                    ((flags & FLAG_MINALIGN) != 0)
480 {
481         if (m_singleLayerBind)
482                 DE_ASSERT(m_texture.numLayers() > 1);
483 }
484
485 void StoreTest::checkSupport (Context& context) const
486 {
487         const VkFormatProperties3KHR formatProperties (context.getFormatProperties(m_format));
488
489         if (!m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
490                 TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
491
492         if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
493                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
494
495         if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
496                 TCU_THROW(NotSupportedError, "Format not supported for storage images");
497
498         if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
499                 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
500 }
501
502 void StoreTest::initPrograms (SourceCollections& programCollection) const
503 {
504         const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
505         const float storeColorBias = computeStoreColorBias(m_format);
506         DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
507
508         const deUint32 xMax = m_texture.size().x() - 1;
509         const deUint32 yMax = m_texture.size().y() - 1;
510         const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
511         const bool storeNegativeValues = isSignedFormat(m_format) && (storeColorBias == 0);
512         bool useClamp = false;
513         std::string colorBaseExpr = signednessPrefix + "vec4("
514                 + "gx^gy^gz, "
515                 + "(" + de::toString(xMax) + "-gx)^gy^gz, "
516                 + "gx^(" + de::toString(yMax) + "-gy)^gz, "
517                 + "(" + de::toString(xMax) + "-gx)^(" + de::toString(yMax) + "-gy)^gz)";
518
519         // Large integer values may not be represented with formats with low bit depths
520         if (isIntegerFormat(m_format))
521         {
522                 const deInt64 minStoreValue = storeNegativeValues ? 0 - deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : 0;
523                 const deInt64 maxStoreValue = storeNegativeValues ? deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : de::max(xMax, yMax);
524
525                 useClamp = !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(minStoreValue), mapVkFormat(m_format)) ||
526                                    !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(maxStoreValue), mapVkFormat(m_format));
527         }
528
529         // Clamp if integer value cannot be represented with the current format
530         if (useClamp)
531         {
532                 const tcu::IVec4 bitDepths = tcu::getTextureFormatBitDepth(mapVkFormat(m_format));
533                 tcu::IVec4 minRepresentableValue;
534                 tcu::IVec4 maxRepresentableValue;
535
536                 switch (tcu::getTextureChannelClass(mapVkFormat(m_format).type))
537                 {
538                         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
539                         {
540                                 minRepresentableValue = tcu::IVec4(0);
541                                 maxRepresentableValue = (tcu::IVec4(1) << bitDepths) - tcu::IVec4(1);
542                                 break;
543                         }
544
545                         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
546                         {
547                                 minRepresentableValue = -(tcu::IVec4(1) << bitDepths - tcu::IVec4(1));
548                                 maxRepresentableValue = (tcu::IVec4(1) << (bitDepths - tcu::IVec4(1))) - tcu::IVec4(1);
549                                 break;
550                         }
551
552                         default:
553                                 DE_ASSERT(isIntegerFormat(m_format));
554                 }
555
556                 colorBaseExpr = "clamp(" + colorBaseExpr + ", "
557                                                 + signednessPrefix + "vec4" + de::toString(minRepresentableValue) + ", "
558                                                 + signednessPrefix + "vec4" + de::toString(maxRepresentableValue) + ")";
559         }
560
561         std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
562                                                         + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
563
564         if (storeNegativeValues)
565                 colorExpr += "-" + de::toString(deRoundFloatToInt32((float)deMax32(xMax, yMax) / 2.0f));
566
567         const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
568         const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
569
570         const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
571         const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
572
573         std::ostringstream src;
574         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
575                 << "\n"
576                 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
577         if (m_declareImageFormatInShader)
578         {
579                 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
580                 src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
581         }
582         else
583                 src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
584
585         if (m_singleLayerBind)
586                 src << "layout (binding = 1) readonly uniform Constants {\n"
587                         << "    int u_layerNdx;\n"
588                         << "};\n";
589
590         src << "\n"
591                 << "void main (void)\n"
592                 << "{\n"
593                 << "    int gx = int(gl_GlobalInvocationID.x);\n"
594                 << "    int gy = int(gl_GlobalInvocationID.y);\n"
595                 << "    int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
596                 << "    imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
597                 << "}\n";
598
599         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
600 }
601
602 //! Generic test iteration algorithm for image tests
603 class BaseTestInstance : public TestInstance
604 {
605 public:
606                                                                         BaseTestInstance                                                (Context&               context,
607                                                                                                                                                          const Texture& texture,
608                                                                                                                                                          const VkFormat format,
609                                                                                                                                                          const bool             declareImageFormatInShader,
610                                                                                                                                                          const bool             singleLayerBind,
611                                                                                                                                                          const bool             minalign,
612                                                                                                                                                          const bool             bufferLoadUniform);
613
614         tcu::TestStatus                                 iterate                                                                 (void);
615
616         virtual                                                 ~BaseTestInstance                                               (void) {}
617
618 protected:
619         virtual VkDescriptorSetLayout   prepareDescriptors                                              (void) = 0;
620         virtual tcu::TestStatus                 verifyResult                                                    (void) = 0;
621
622         virtual void                                    commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer) = 0;
623         virtual void                                    commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer) = 0;
624         virtual void                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer) = 0;
625
626         virtual void                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
627                                                                                                                                                          const VkPipelineLayout pipelineLayout,
628                                                                                                                                                          const int                              layerNdx) = 0;
629         virtual deUint32                                getViewOffset                                                   (Context&               context,
630                                                                                                                                                          const VkFormat format,
631                                                                                                                                                          bool                   uniform);
632
633         const Texture                                   m_texture;
634         const VkFormat                                  m_format;
635         const bool                                              m_declareImageFormatInShader;
636         const bool                                              m_singleLayerBind;
637         const bool                                              m_minalign;
638         const bool                                              m_bufferLoadUniform;
639         const deUint32                                  m_srcViewOffset;
640         const deUint32                                  m_dstViewOffset;
641 };
642
643 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool bufferLoadUniform)
644         : TestInstance                                  (context)
645         , m_texture                                             (texture)
646         , m_format                                              (format)
647         , m_declareImageFormatInShader  (declareImageFormatInShader)
648         , m_singleLayerBind                             (singleLayerBind)
649         , m_minalign                                    (minalign)
650         , m_bufferLoadUniform                   (bufferLoadUniform)
651         , m_srcViewOffset                               (getViewOffset(context, format, m_bufferLoadUniform))
652         , m_dstViewOffset                               (getViewOffset(context, formatHasThreeComponents(format) ? getSingleComponentFormat(format) : format, false))
653 {
654 }
655
656 tcu::TestStatus BaseTestInstance::iterate (void)
657 {
658         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
659         const VkDevice                                  device                          = m_context.getDevice();
660         const VkQueue                                   queue                           = m_context.getUniversalQueue();
661         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
662
663         const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
664
665         const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
666         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
667         const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
668
669         const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
670         const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
671
672         beginCommandBuffer(vk, *cmdBuffer);
673
674         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
675         commandBeforeCompute(*cmdBuffer);
676
677         const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
678         const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
679         for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
680         {
681                 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
682
683                 if (layerNdx > 0)
684                         commandBetweenShaderInvocations(*cmdBuffer);
685
686                 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
687         }
688
689         commandAfterCompute(*cmdBuffer);
690
691         endCommandBuffer(vk, *cmdBuffer);
692
693         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
694
695         return verifyResult();
696 }
697
698 //! Base store test implementation
699 class StoreTestInstance : public BaseTestInstance
700 {
701 public:
702                                                                         StoreTestInstance                                               (Context&               context,
703                                                                                                                                                          const Texture& texture,
704                                                                                                                                                          const VkFormat format,
705                                                                                                                                                          const bool             declareImageFormatInShader,
706                                                                                                                                                          const bool             singleLayerBind,
707                                                                                                                                                          const bool             minalign);
708
709 protected:
710         virtual tcu::TestStatus                 verifyResult                                                    (void);
711
712         // Add empty implementations for functions that might be not needed
713         void                                                    commandBeforeCompute                                    (const VkCommandBuffer) {}
714         void                                                    commandBetweenShaderInvocations                 (const VkCommandBuffer) {}
715         void                                                    commandAfterCompute                                             (const VkCommandBuffer) {}
716
717         de::MovePtr<Buffer>                             m_imageBuffer;
718         const VkDeviceSize                              m_imageSizeBytes;
719 };
720
721 deUint32 BaseTestInstance::getViewOffset(Context&                       context,
722                                                                                  const VkFormat         format,
723                                                                                  bool                           uniform)
724 {
725         if (m_minalign)
726         {
727                 if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
728                         return (deUint32)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
729
730                 VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
731                 deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
732                 alignmentProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
733
734                 VkPhysicalDeviceProperties2 properties2;
735                 deMemset(&properties2, 0, sizeof(properties2));
736                 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
737                 properties2.pNext = &alignmentProperties;
738
739                 context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
740
741                 VkBool32 singleTexelAlignment = uniform ? alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
742                                                                                                   alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
743                 VkDeviceSize align = uniform ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
744                                                                            alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
745
746                 VkDeviceSize texelSize = formatHasThreeComponents(format) ? tcu::getChannelSize(vk::mapVkFormat(format).type) : tcu::getPixelSize(vk::mapVkFormat(format));
747
748                 if (singleTexelAlignment)
749                         align = de::min(align, texelSize);
750
751                 return (deUint32)align;
752         }
753
754         return 0;
755 }
756
757 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign)
758         : BaseTestInstance              (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, false)
759         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
760 {
761         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
762         const VkDevice                  device          = m_context.getDevice();
763         Allocator&                              allocator       = m_context.getDefaultAllocator();
764
765         // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
766
767         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
768                 vk, device, allocator,
769                 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
770                 MemoryRequirement::HostVisible));
771 }
772
773 tcu::TestStatus StoreTestInstance::verifyResult (void)
774 {
775         const DeviceInterface&  vk              = m_context.getDeviceInterface();
776         const VkDevice                  device  = m_context.getDevice();
777
778         const tcu::IVec3 imageSize = m_texture.size();
779         const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
780
781         const Allocation& alloc = m_imageBuffer->getAllocation();
782         invalidateAlloc(vk, device, alloc);
783         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, (const char *)alloc.getHostPtr() + m_dstViewOffset);
784
785         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
786                 return tcu::TestStatus::pass("Passed");
787         else
788                 return tcu::TestStatus::fail("Image comparison failed");
789 }
790
791 //! Store test for images
792 class ImageStoreTestInstance : public StoreTestInstance
793 {
794 public:
795                                                                                 ImageStoreTestInstance                                  (Context&                               context,
796                                                                                                                                                                  const Texture&                 texture,
797                                                                                                                                                                  const VkFormat                 format,
798                                                                                                                                                                  const bool                             declareImageFormatInShader,
799                                                                                                                                                                  const bool                             singleLayerBind,
800                                                                                                                                                                  const bool                             minalign);
801
802 protected:
803         VkDescriptorSetLayout                           prepareDescriptors                                              (void);
804         void                                                            commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer);
805         void                                                            commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer);
806         void                                                            commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
807
808         void                                                            commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
809                                                                                                                                                                  const VkPipelineLayout pipelineLayout,
810                                                                                                                                                                  const int                              layerNdx);
811
812         de::MovePtr<Image>                                      m_image;
813         de::MovePtr<Buffer>                                     m_constantsBuffer;
814         const VkDeviceSize                                      m_constantsBufferChunkSizeBytes;
815         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
816         Move<VkDescriptorPool>                          m_descriptorPool;
817         std::vector<SharedVkDescriptorSet>      m_allDescriptorSets;
818         std::vector<SharedVkImageView>          m_allImageViews;
819 };
820
821 ImageStoreTestInstance::ImageStoreTestInstance (Context&                context,
822                                                                                                 const Texture&  texture,
823                                                                                                 const VkFormat  format,
824                                                                                                 const bool              declareImageFormatInShader,
825                                                                                                 const bool              singleLayerBind,
826                                                                                                 const bool              minalign)
827         : StoreTestInstance                                     (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign)
828         , m_constantsBufferChunkSizeBytes       (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
829         , m_allDescriptorSets                           (texture.numLayers())
830         , m_allImageViews                                       (texture.numLayers())
831 {
832         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
833         const VkDevice                  device          = m_context.getDevice();
834         Allocator&                              allocator       = m_context.getDefaultAllocator();
835
836         m_image = de::MovePtr<Image>(new Image(
837                 vk, device, allocator,
838                 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
839                 MemoryRequirement::Any));
840
841         // This buffer will be used to pass constants to the shader
842
843         const int numLayers = m_texture.numLayers();
844         const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
845         m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
846                 vk, device, allocator,
847                 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
848                 MemoryRequirement::HostVisible));
849
850         {
851                 const Allocation& alloc = m_constantsBuffer->getAllocation();
852                 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
853
854                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
855
856                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
857                 {
858                         deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
859                         *valuePtr = static_cast<deUint32>(layerNdx);
860                 }
861
862                 flushAlloc(vk, device, alloc);
863         }
864 }
865
866 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
867 {
868         const DeviceInterface&  vk              = m_context.getDeviceInterface();
869         const VkDevice                  device  = m_context.getDevice();
870
871         const int numLayers = m_texture.numLayers();
872         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
873                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
874                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
875                 .build(vk, device);
876
877         m_descriptorPool = DescriptorPoolBuilder()
878                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
879                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
880                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
881
882         if (m_singleLayerBind)
883         {
884                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
885                 {
886                         m_allDescriptorSets[layerNdx]   = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
887                         m_allImageViews[layerNdx]               = makeVkSharedPtr(makeImageView(
888                                                                                                 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
889                                                                                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
890                 }
891         }
892         else // bind all layers at once
893         {
894                 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
895                 m_allImageViews[0] = makeVkSharedPtr(makeImageView(
896                                                                 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
897                                                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
898         }
899
900         return *m_descriptorSetLayout;  // not passing the ownership
901 }
902
903 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
904 {
905         const DeviceInterface&  vk              = m_context.getDeviceInterface();
906         const VkDevice                  device  = m_context.getDevice();
907
908         const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
909         const VkImageView imageView = **m_allImageViews[layerNdx];
910
911         const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
912
913         // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
914         const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
915                 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
916
917         DescriptorSetUpdateBuilder()
918                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
919                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
920                 .update(vk, device);
921         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
922 }
923
924 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
925 {
926         const DeviceInterface& vk = m_context.getDeviceInterface();
927
928         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
929         const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
930                 0u, VK_ACCESS_SHADER_WRITE_BIT,
931                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
932                 m_image->get(), fullImageSubresourceRange);
933
934         const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
935         const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
936                 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
937                 m_constantsBuffer->get(), 0ull, constantsBufferSize);
938
939         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
940 }
941
942 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
943 {
944         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
945 }
946
947 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
948 {
949         commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
950 }
951
952 //! Store test for buffers
953 class BufferStoreTestInstance : public StoreTestInstance
954 {
955 public:
956                                                                         BufferStoreTestInstance                                 (Context&                               context,
957                                                                                                                                                          const Texture&                 texture,
958                                                                                                                                                          const VkFormat                 format,
959                                                                                                                                                          const bool                             declareImageFormatInShader,
960                                                                                                                                                          const bool                             minalign);
961
962 protected:
963         VkDescriptorSetLayout                   prepareDescriptors                                              (void);
964         void                                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
965
966         void                                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
967                                                                                                                                                          const VkPipelineLayout pipelineLayout,
968                                                                                                                                                          const int                              layerNdx);
969
970         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
971         Move<VkDescriptorPool>                  m_descriptorPool;
972         Move<VkDescriptorSet>                   m_descriptorSet;
973         Move<VkBufferView>                              m_bufferView;
974 };
975
976 BufferStoreTestInstance::BufferStoreTestInstance (Context&                      context,
977                                                                                                   const Texture&        texture,
978                                                                                                   const VkFormat        format,
979                                                                                                   const bool            declareImageFormatInShader,
980                                                                                                   const bool            minalign)
981         : StoreTestInstance(context, texture, format, declareImageFormatInShader, false, minalign)
982 {
983 }
984
985 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
986 {
987         const DeviceInterface&  vk              = m_context.getDeviceInterface();
988         const VkDevice                  device  = m_context.getDevice();
989
990         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
991                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
992                 .build(vk, device);
993
994         m_descriptorPool = DescriptorPoolBuilder()
995                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
996                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
997
998         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
999         m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_dstViewOffset, m_imageSizeBytes);
1000
1001         return *m_descriptorSetLayout;  // not passing the ownership
1002 }
1003
1004 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1005 {
1006         DE_ASSERT(layerNdx == 0);
1007         DE_UNREF(layerNdx);
1008
1009         const VkDevice                  device  = m_context.getDevice();
1010         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1011
1012         DescriptorSetUpdateBuilder()
1013                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
1014                 .update(vk, device);
1015         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1016 }
1017
1018 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1019 {
1020         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes + m_dstViewOffset);
1021 }
1022
1023 class LoadStoreTest : public TestCase
1024 {
1025 public:
1026         enum TestFlags
1027         {
1028                 FLAG_SINGLE_LAYER_BIND                          = 1 << 0,       //!< Run the shader multiple times, each time binding a different layer.
1029                 FLAG_RESTRICT_IMAGES                            = 1 << 1,       //!< If given, images in the shader will be qualified with "restrict".
1030                 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER     = 1 << 2,       //!< Declare the format of the images in the shader code
1031                 FLAG_MINALIGN                                           = 1 << 3,       //!< Use bufferview offset that matches the advertised minimum alignment
1032                 FLAG_UNIFORM_TEXEL_BUFFER                       = 1 << 4,       //!< Load from a uniform texel buffer rather than a storage texel buffer
1033         };
1034
1035                                                         LoadStoreTest                   (tcu::TestContext&              testCtx,
1036                                                                                                          const std::string&             name,
1037                                                                                                          const std::string&             description,
1038                                                                                                          const Texture&                 texture,
1039                                                                                                          const VkFormat                 format,
1040                                                                                                          const VkFormat                 imageFormat,
1041                                                                                                          const deUint32                 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER,
1042                                                                                                          const deBool                   imageLoadStoreLodAMD = DE_FALSE);
1043
1044         virtual void                    checkSupport                    (Context&                               context) const;
1045         void                                    initPrograms                    (SourceCollections&             programCollection) const;
1046         TestInstance*                   createInstance                  (Context&                               context) const;
1047
1048 private:
1049         const Texture                   m_texture;
1050         const VkFormat                  m_format;                                               //!< Format as accessed in the shader
1051         const VkFormat                  m_imageFormat;                                  //!< Storage format
1052         const bool                              m_declareImageFormatInShader;   //!< Whether the shader will specify the format layout qualifier of the images
1053         const bool                              m_singleLayerBind;
1054         const bool                              m_restrictImages;
1055         const bool                              m_minalign;
1056         bool                                    m_bufferLoadUniform;
1057         const deBool                    m_imageLoadStoreLodAMD;
1058 };
1059
1060 LoadStoreTest::LoadStoreTest (tcu::TestContext&         testCtx,
1061                                                           const std::string&    name,
1062                                                           const std::string&    description,
1063                                                           const Texture&                texture,
1064                                                           const VkFormat                format,
1065                                                           const VkFormat                imageFormat,
1066                                                           const deUint32                flags,
1067                                                           const deBool                  imageLoadStoreLodAMD)
1068         : TestCase                                              (testCtx, name, description)
1069         , m_texture                                             (texture)
1070         , m_format                                              (format)
1071         , m_imageFormat                                 (imageFormat)
1072         , m_declareImageFormatInShader  ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
1073         , m_singleLayerBind                             ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
1074         , m_restrictImages                              ((flags & FLAG_RESTRICT_IMAGES) != 0)
1075         , m_minalign                                    ((flags & FLAG_MINALIGN) != 0)
1076         , m_bufferLoadUniform                   ((flags & FLAG_UNIFORM_TEXEL_BUFFER) != 0)
1077         , m_imageLoadStoreLodAMD                (imageLoadStoreLodAMD)
1078 {
1079         if (m_singleLayerBind)
1080                 DE_ASSERT(m_texture.numLayers() > 1);
1081
1082         DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
1083 }
1084
1085 void LoadStoreTest::checkSupport (Context& context) const
1086 {
1087         const VkFormatProperties3KHR formatProperties (context.getFormatProperties(m_format));
1088         const VkFormatProperties3KHR imageFormatProperties (context.getFormatProperties(m_imageFormat));
1089
1090         if (m_imageLoadStoreLodAMD)
1091                 context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1092
1093         if (!m_bufferLoadUniform && !m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR))
1094                 TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via storage images");
1095
1096         if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1097                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1098
1099         if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1100                 TCU_THROW(NotSupportedError, "Format not supported for storage images");
1101
1102         if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1103                 TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1104
1105         if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageFormatProperties.optimalTilingFeatures))
1106                 TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1107
1108         if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1109                 TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1110
1111         if (formatHasThreeComponents(m_format))
1112         {
1113                 // When the source buffer is three-component, the destination buffer is single-component.
1114                 VkFormat dstFormat = getSingleComponentFormat(m_format);
1115                 const VkFormatProperties3KHR dstFormatProperties (context.getFormatProperties(dstFormat));
1116
1117                 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1118                         TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1119         }
1120         else
1121                 if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1122                         TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1123
1124         if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1125                 TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1126 }
1127
1128 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
1129 {
1130         const tcu::TextureFormat        texFormat                       = mapVkFormat(m_format);
1131         const int                                       dimension                       = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
1132         const ImageType                         usedImageType           = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
1133         const std::string                       formatQualifierStr      = getShaderImageFormatQualifier(texFormat);
1134         const std::string                       uniformTypeStr          = getFormatPrefix(texFormat) + "textureBuffer";
1135         const std::string                       imageTypeStr            = getShaderImageType(texFormat, usedImageType);
1136         const std::string                       maybeRestrictStr        = (m_restrictImages ? "restrict " : "");
1137         const std::string                       xMax                            = de::toString(m_texture.size().x() - 1);
1138
1139         std::ostringstream src;
1140         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1141                 << "\n";
1142         if (!m_declareImageFormatInShader)
1143         {
1144                 src << "#extension GL_EXT_shader_image_load_formatted : require\n";
1145         }
1146
1147         if (m_imageLoadStoreLodAMD)
1148         {
1149                 src << "#extension GL_AMD_shader_image_load_store_lod : require\n";
1150         }
1151
1152         src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
1153         if (m_bufferLoadUniform)
1154                 src << "layout (binding = 0) uniform " << uniformTypeStr << " u_image0;\n";
1155         else if (m_declareImageFormatInShader)
1156                 src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1157         else
1158                 src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1159
1160         if (formatHasThreeComponents(m_format))
1161                 src << "layout (binding = 1) " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1162         else
1163                 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1164
1165         src << "\n"
1166                 << "void main (void)\n"
1167                 << "{\n";
1168         switch (dimension)
1169         {
1170         default: DE_ASSERT(0); // fallthrough
1171         case 1:
1172                 if (m_bufferLoadUniform)
1173                 {
1174                         // for three-component formats, the dst buffer is single-component and the shader
1175                         // expands the store into 3 component-wise stores.
1176                         std::string type = getFormatPrefix(texFormat) + "vec4";
1177                         src << "    int pos = int(gl_GlobalInvocationID.x);\n"
1178                                    "    " << type << " t = texelFetch(u_image0, " + xMax + "-pos);\n";
1179                         if (formatHasThreeComponents(m_format))
1180                         {
1181                                 src << "    imageStore(u_image1, 3*pos+0, " << type << "(t.x));\n";
1182                                 src << "    imageStore(u_image1, 3*pos+1, " << type << "(t.y));\n";
1183                                 src << "    imageStore(u_image1, 3*pos+2, " << type << "(t.z));\n";
1184                         }
1185                         else
1186                                 src << "    imageStore(u_image1, pos, t);\n";
1187                 }
1188                 else if (m_imageLoadStoreLodAMD)
1189                 {
1190                         src <<
1191                                 "    int pos = int(gl_GlobalInvocationID.x);\n";
1192
1193                         for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1194                         {
1195                                 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1196                                 src << "    imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, " + xMaxSize + "-pos, " + de::toString(levelNdx) + "));\n";
1197                         }
1198                 }
1199                 else
1200                 {
1201                         src <<
1202                                 "    int pos = int(gl_GlobalInvocationID.x);\n"
1203                                 "    imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n";
1204                 }
1205                 break;
1206         case 2:
1207                 if (m_imageLoadStoreLodAMD)
1208                 {
1209                         src << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
1210
1211                         for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1212                         {
1213                                 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1214                                 src << "    imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec2(" + xMaxSize + "-pos.x, pos.y), " + de::toString(levelNdx) + "));\n";
1215                         }
1216
1217                 }
1218                 else
1219                 {
1220                         src <<
1221                                 "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
1222                                 "    imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n";
1223                 }
1224                 break;
1225         case 3:
1226                 if (m_imageLoadStoreLodAMD)
1227                 {
1228                         src << "    ivec3 pos = ivec3(gl_GlobalInvocationID);\n";
1229
1230                         for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1231                         {
1232                                 std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1233                                 src << "    imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec3(" + xMaxSize + "-pos.x, pos.y, pos.z), " + de::toString(levelNdx) + "));\n";
1234                         }
1235                 }
1236                 else
1237                 {
1238                         src <<
1239                                 "    ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
1240                                 "    imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n";
1241                 }
1242                 break;
1243         }
1244         src << "}\n";
1245
1246         programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1247 }
1248
1249 //! Load/store test base implementation
1250 class LoadStoreTestInstance : public BaseTestInstance
1251 {
1252 public:
1253                                                                         LoadStoreTestInstance                           (Context&                       context,
1254                                                                                                                                                  const Texture&         texture,
1255                                                                                                                                                  const VkFormat         format,
1256                                                                                                                                                  const VkFormat         imageFormat,
1257                                                                                                                                                  const bool                     declareImageFormatInShader,
1258                                                                                                                                                  const bool                     singleLayerBind,
1259                                                                                                                                                  const bool                     minalign,
1260                                                                                                                                                  const bool                     bufferLoadUniform);
1261
1262 protected:
1263         virtual Buffer*                                 getResultBuffer                                         (void) const = 0;       //!< Get the buffer that contains the result image
1264
1265         tcu::TestStatus                                 verifyResult                                            (void);
1266
1267         // Add empty implementations for functions that might be not needed
1268         void                                                    commandBeforeCompute                            (const VkCommandBuffer) {}
1269         void                                                    commandBetweenShaderInvocations         (const VkCommandBuffer) {}
1270         void                                                    commandAfterCompute                                     (const VkCommandBuffer) {}
1271
1272         de::MovePtr<Buffer>                             m_imageBuffer;          //!< Source data and helper buffer
1273         const VkDeviceSize                              m_imageSizeBytes;
1274         const VkFormat                                  m_imageFormat;          //!< Image format (for storage, may be different than texture format)
1275         tcu::TextureLevel                               m_referenceImage;       //!< Used as input data and later to verify result image
1276
1277         bool                                                    m_bufferLoadUniform;
1278         VkDescriptorType                                m_bufferLoadDescriptorType;
1279         VkBufferUsageFlagBits                   m_bufferLoadUsageBit;
1280 };
1281
1282 LoadStoreTestInstance::LoadStoreTestInstance (Context&                  context,
1283                                                                                           const Texture&        texture,
1284                                                                                           const VkFormat        format,
1285                                                                                           const VkFormat        imageFormat,
1286                                                                                           const bool            declareImageFormatInShader,
1287                                                                                           const bool            singleLayerBind,
1288                                                                                           const bool            minalign,
1289                                                                                           const bool            bufferLoadUniform)
1290         : BaseTestInstance              (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1291         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
1292         , m_imageFormat                 (imageFormat)
1293         , m_referenceImage              (generateReferenceImage(texture.size(), imageFormat, format))
1294         , m_bufferLoadUniform   (bufferLoadUniform)
1295 {
1296         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1297         const VkDevice                  device          = m_context.getDevice();
1298         Allocator&                              allocator       = m_context.getDefaultAllocator();
1299
1300         m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1301         m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1302
1303         // A helper buffer with enough space to hold the whole image.
1304
1305         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1306                 vk, device, allocator,
1307                 makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1308                 MemoryRequirement::HostVisible));
1309
1310         // Copy reference data to buffer for subsequent upload to image.
1311
1312         const Allocation& alloc = m_imageBuffer->getAllocation();
1313         deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset, m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
1314         flushAlloc(vk, device, alloc);
1315 }
1316
1317 tcu::TestStatus LoadStoreTestInstance::verifyResult     (void)
1318 {
1319         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1320         const VkDevice                  device  = m_context.getDevice();
1321
1322         // Apply the same transformation as done in the shader
1323         const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1324         flipHorizontally(reference);
1325
1326         const Allocation& alloc = getResultBuffer()->getAllocation();
1327         invalidateAlloc(vk, device, alloc);
1328         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), (const char *)alloc.getHostPtr() + m_dstViewOffset);
1329
1330         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1331                 return tcu::TestStatus::pass("Passed");
1332         else
1333                 return tcu::TestStatus::fail("Image comparison failed");
1334 }
1335
1336 //! Load/store test for images
1337 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
1338 {
1339 public:
1340                                                                                 ImageLoadStoreTestInstance                      (Context&                               context,
1341                                                                                                                                                          const Texture&                 texture,
1342                                                                                                                                                          const VkFormat                 format,
1343                                                                                                                                                          const VkFormat                 imageFormat,
1344                                                                                                                                                          const bool                             declareImageFormatInShader,
1345                                                                                                                                                          const bool                             singleLayerBind,
1346                                                                                                                                                          const bool                             minalign,
1347                                                                                                                                                          const bool                             bufferLoadUniform);
1348
1349 protected:
1350         VkDescriptorSetLayout                           prepareDescriptors                                      (void);
1351         void                                                            commandBeforeCompute                            (const VkCommandBuffer  cmdBuffer);
1352         void                                                            commandBetweenShaderInvocations         (const VkCommandBuffer  cmdBuffer);
1353         void                                                            commandAfterCompute                                     (const VkCommandBuffer  cmdBuffer);
1354
1355         void                                                            commandBindDescriptorsForLayer          (const VkCommandBuffer  cmdBuffer,
1356                                                                                                                                                          const VkPipelineLayout pipelineLayout,
1357                                                                                                                                                          const int                              layerNdx);
1358
1359         Buffer*                                                         getResultBuffer                                         (void) const { return m_imageBuffer.get(); }
1360
1361         de::MovePtr<Image>                                      m_imageSrc;
1362         de::MovePtr<Image>                                      m_imageDst;
1363         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
1364         Move<VkDescriptorPool>                          m_descriptorPool;
1365         std::vector<SharedVkDescriptorSet>      m_allDescriptorSets;
1366         std::vector<SharedVkImageView>          m_allSrcImageViews;
1367         std::vector<SharedVkImageView>          m_allDstImageViews;
1368 };
1369
1370 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context&                context,
1371                                                                                                                 const Texture&  texture,
1372                                                                                                                 const VkFormat  format,
1373                                                                                                                 const VkFormat  imageFormat,
1374                                                                                                                 const bool              declareImageFormatInShader,
1375                                                                                                                 const bool              singleLayerBind,
1376                                                                                                                 const bool              minalign,
1377                                                                                                                 const bool              bufferLoadUniform)
1378         : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1379         , m_allDescriptorSets   (texture.numLayers())
1380         , m_allSrcImageViews    (texture.numLayers())
1381         , m_allDstImageViews    (texture.numLayers())
1382 {
1383         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
1384         const VkDevice                          device                          = m_context.getDevice();
1385         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
1386         const VkImageCreateFlags        imageFlags                      = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1387
1388         m_imageSrc = de::MovePtr<Image>(new Image(
1389                 vk, device, allocator,
1390                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1391                 MemoryRequirement::Any));
1392
1393         m_imageDst = de::MovePtr<Image>(new Image(
1394                 vk, device, allocator,
1395                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1396                 MemoryRequirement::Any));
1397 }
1398
1399 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1400 {
1401         const VkDevice                  device  = m_context.getDevice();
1402         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1403
1404         const int numLayers = m_texture.numLayers();
1405         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1406                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1407                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1408                 .build(vk, device);
1409
1410         m_descriptorPool = DescriptorPoolBuilder()
1411                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1412                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1413                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1414
1415         if (m_singleLayerBind)
1416         {
1417                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1418                 {
1419                         const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1420                         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1421
1422                         m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1423                         m_allSrcImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1424                         m_allDstImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1425                 }
1426         }
1427         else // bind all layers at once
1428         {
1429                 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1430                 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1431
1432                 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1433                 m_allSrcImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1434                 m_allDstImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1435         }
1436
1437         return *m_descriptorSetLayout;  // not passing the ownership
1438 }
1439
1440 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1441 {
1442         const VkDevice                  device  = m_context.getDevice();
1443         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1444
1445         const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1446         const VkImageView         srcImageView  = **m_allSrcImageViews[layerNdx];
1447         const VkImageView         dstImageView  = **m_allDstImageViews[layerNdx];
1448
1449         const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1450         const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1451
1452         DescriptorSetUpdateBuilder()
1453                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1454                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1455                 .update(vk, device);
1456         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1457 }
1458
1459 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1460 {
1461         const DeviceInterface& vk = m_context.getDeviceInterface();
1462
1463         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1464         {
1465                 const VkImageMemoryBarrier preCopyImageBarriers[] =
1466                 {
1467                         makeImageMemoryBarrier(
1468                                 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1469                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1470                                 m_imageSrc->get(), fullImageSubresourceRange),
1471                         makeImageMemoryBarrier(
1472                                 0u, VK_ACCESS_SHADER_WRITE_BIT,
1473                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1474                                 m_imageDst->get(), fullImageSubresourceRange)
1475                 };
1476
1477                 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1478                         VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1479                         m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1480
1481                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1482                         (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1483         }
1484         {
1485                 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1486                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1487                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1488                         m_imageSrc->get(), fullImageSubresourceRange);
1489
1490                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1491
1492                 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1493                 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);
1494         }
1495 }
1496
1497 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1498 {
1499         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1500 }
1501
1502 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1503 {
1504         commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1505 }
1506
1507 //! Load/store Lod AMD test for images
1508 class ImageLoadStoreLodAMDTestInstance : public BaseTestInstance
1509 {
1510 public:
1511                                                                                 ImageLoadStoreLodAMDTestInstance        (Context&                               context,
1512                                                                                                                                                          const Texture&                 texture,
1513                                                                                                                                                          const VkFormat                 format,
1514                                                                                                                                                          const VkFormat                 imageFormat,
1515                                                                                                                                                          const bool                             declareImageFormatInShader,
1516                                                                                                                                                          const bool                             singleLayerBind,
1517                                                                                                                                                          const bool                             minalign,
1518                                                                                                                                                          const bool                             bufferLoadUniform);
1519
1520 protected:
1521         VkDescriptorSetLayout                           prepareDescriptors                                      (void);
1522         void                                                            commandBeforeCompute                            (const VkCommandBuffer  cmdBuffer);
1523         void                                                            commandBetweenShaderInvocations         (const VkCommandBuffer  cmdBuffer);
1524         void                                                            commandAfterCompute                                     (const VkCommandBuffer  cmdBuffer);
1525
1526         void                                                            commandBindDescriptorsForLayer          (const VkCommandBuffer  cmdBuffer,
1527                                                                                                                                                          const VkPipelineLayout pipelineLayout,
1528                                                                                                                                                          const int                              layerNdx);
1529
1530         Buffer*                                                         getResultBuffer                                         (void) const { return m_imageBuffer.get(); }
1531         tcu::TestStatus                                         verifyResult                                            (void);
1532
1533         de::MovePtr<Buffer>                                     m_imageBuffer;          //!< Source data and helper buffer
1534         const VkDeviceSize                                      m_imageSizeBytes;
1535         const VkFormat                                          m_imageFormat;          //!< Image format (for storage, may be different than texture format)
1536         std::vector<tcu::TextureLevel>          m_referenceImages;      //!< Used as input data and later to verify result image
1537
1538         bool                                                            m_bufferLoadUniform;
1539         VkDescriptorType                                        m_bufferLoadDescriptorType;
1540         VkBufferUsageFlagBits                           m_bufferLoadUsageBit;
1541
1542         de::MovePtr<Image>                                      m_imageSrc;
1543         de::MovePtr<Image>                                      m_imageDst;
1544         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
1545         Move<VkDescriptorPool>                          m_descriptorPool;
1546         std::vector<SharedVkDescriptorSet>  m_allDescriptorSets;
1547         std::vector<SharedVkImageView>      m_allSrcImageViews;
1548         std::vector<SharedVkImageView>      m_allDstImageViews;
1549
1550 };
1551
1552 ImageLoadStoreLodAMDTestInstance::ImageLoadStoreLodAMDTestInstance (Context&            context,
1553                                                                                                                                         const Texture&  texture,
1554                                                                                                                                         const VkFormat  format,
1555                                                                                                                                         const VkFormat  imageFormat,
1556                                                                                                                                         const bool              declareImageFormatInShader,
1557                                                                                                                                         const bool              singleLayerBind,
1558                                                                                                                                         const bool              minalign,
1559                                                                                                                                         const bool              bufferLoadUniform)
1560         : BaseTestInstance                      (context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1561         , m_imageSizeBytes                      (getMipmapImageTotalSizeBytes(texture, format))
1562         , m_imageFormat                         (imageFormat)
1563         , m_bufferLoadUniform           (bufferLoadUniform)
1564         , m_allDescriptorSets       (texture.numLayers())
1565         , m_allSrcImageViews        (texture.numLayers())
1566         , m_allDstImageViews        (texture.numLayers())
1567 {
1568         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
1569         const VkDevice                          device                          = m_context.getDevice();
1570         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
1571         const VkImageCreateFlags        imageFlags                      = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1572
1573         const VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(m_texture.numSamples());       // integer and bit mask are aligned, so we can cast like this
1574
1575         for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1576         {
1577                 tcu::TextureLevel referenceImage = generateReferenceImage(texture.size(levelNdx), imageFormat, format);
1578                 m_referenceImages.push_back(referenceImage);
1579         }
1580
1581         m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1582         m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1583
1584         // A helper buffer with enough space to hold the whole image.
1585         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
1586                                                                                                    vk, device, allocator,
1587                                                                                                    makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1588                                                                                                    MemoryRequirement::HostVisible));
1589
1590         // Copy reference data to buffer for subsequent upload to image.
1591         {
1592                 const Allocation& alloc = m_imageBuffer->getAllocation();
1593                 VkDeviceSize bufferOffset = 0u;
1594                 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1595                 {
1596                         deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset + bufferOffset, m_referenceImages[levelNdx].getAccess().getDataPtr(), static_cast<size_t>(getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx)));
1597                         bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1598                 }
1599                 flushAlloc(vk, device, alloc);
1600         }
1601
1602         {
1603                 const VkImageCreateInfo imageParamsSrc =
1604                 {
1605                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                                                                            // VkStructureType                      sType;
1606                         DE_NULL,                                                                                                                                                                                        // const void*                          pNext;
1607                         (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags,        // VkImageCreateFlags           flags;
1608                         mapImageType(m_texture.type()),                                                                                                                                         // VkImageType                          imageType;
1609                         m_imageFormat,                                                                                                                                                                          // VkFormat                                     format;
1610                         makeExtent3D(m_texture.layerSize()),                                                                                                                            // VkExtent3D                           extent;
1611                         (deUint32)m_texture.numMipmapLevels(),                                                                                                                          // deUint32                                     mipLevels;
1612                         (deUint32)m_texture.numLayers(),                                                                                                                                        // deUint32                                     arrayLayers;
1613                         samples,                                                                                                                                                                                        // VkSampleCountFlagBits        samples;
1614                         VK_IMAGE_TILING_OPTIMAL,                                                                                                                                                        // VkImageTiling                        tiling;
1615                         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,                                                                           // VkImageUsageFlags            usage;
1616                         VK_SHARING_MODE_EXCLUSIVE,                                                                                                                                                      // VkSharingMode                        sharingMode;
1617                         0u,                                                                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
1618                         DE_NULL,                                                                                                                                                                                        // const deUint32*                      pQueueFamilyIndices;
1619                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                                                                      // VkImageLayout                        initialLayout;
1620                 };
1621
1622                 m_imageSrc = de::MovePtr<Image>(new Image(
1623                                                                                                   vk, device, allocator,
1624                                                                                                   imageParamsSrc,
1625                                                                                                   MemoryRequirement::Any));
1626         }
1627
1628         {
1629                 const VkImageCreateInfo imageParamsDst =
1630                 {
1631                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                                                                            // VkStructureType                      sType;
1632                         DE_NULL,                                                                                                                                                                                        // const void*                          pNext;
1633                         (isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags,        // VkImageCreateFlags           flags;
1634                         mapImageType(m_texture.type()),                                                                                                                                         // VkImageType                          imageType;
1635                         m_imageFormat,                                                                                                                                                                          // VkFormat                                     format;
1636                         makeExtent3D(m_texture.layerSize()),                                                                                                                            // VkExtent3D                           extent;
1637                         (deUint32)m_texture.numMipmapLevels(),                                                                                                                          // deUint32                                     mipLevels;
1638                         (deUint32)m_texture.numLayers(),                                                                                                                                        // deUint32                                     arrayLayers;
1639                         samples,                                                                                                                                                                                        // VkSampleCountFlagBits        samples;
1640                         VK_IMAGE_TILING_OPTIMAL,                                                                                                                                                        // VkImageTiling                        tiling;
1641                     VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,                                                                               // VkImageUsageFlags            usage;
1642                         VK_SHARING_MODE_EXCLUSIVE,                                                                                                                                                      // VkSharingMode                        sharingMode;
1643                         0u,                                                                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
1644                         DE_NULL,                                                                                                                                                                                        // const deUint32*                      pQueueFamilyIndices;
1645                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                                                                      // VkImageLayout                        initialLayout;
1646                 };
1647
1648                 m_imageDst = de::MovePtr<Image>(new Image(
1649                                                                                                   vk, device, allocator,
1650                                                                                                   imageParamsDst,
1651                                                                                                   MemoryRequirement::Any));
1652         }
1653 }
1654
1655 tcu::TestStatus ImageLoadStoreLodAMDTestInstance::verifyResult  (void)
1656 {
1657         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1658         const VkDevice                  device  = m_context.getDevice();
1659
1660         const Allocation& alloc = getResultBuffer()->getAllocation();
1661         invalidateAlloc(vk, device, alloc);
1662
1663     VkDeviceSize bufferOffset = 0;
1664         for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1665         {
1666                 // Apply the same transformation as done in the shader
1667                 const tcu::PixelBufferAccess reference = m_referenceImages[levelNdx].getAccess();
1668                 flipHorizontally(reference);
1669
1670                 const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(levelNdx), (const char *)alloc.getHostPtr() + m_dstViewOffset + bufferOffset);
1671
1672                 if (!comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result, levelNdx))
1673                 {
1674                         std::ostringstream errorMessage;
1675                         errorMessage << "Image Level " << levelNdx << " comparison failed";
1676                         return tcu::TestStatus::fail(errorMessage.str());
1677                 }
1678                 bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1679         }
1680
1681         return tcu::TestStatus::pass("Passed");
1682 }
1683
1684 VkDescriptorSetLayout ImageLoadStoreLodAMDTestInstance::prepareDescriptors (void)
1685 {
1686         const VkDevice                  device  = m_context.getDevice();
1687         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1688
1689         const int numLayers = m_texture.numLayers();
1690         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1691                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1692                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1693                 .build(vk, device);
1694
1695         m_descriptorPool = DescriptorPoolBuilder()
1696                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1697                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1698                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1699
1700         if (m_singleLayerBind)
1701         {
1702                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1703                 {
1704                         const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1705                         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), layerNdx, 1u);
1706
1707                         m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1708                         m_allSrcImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1709                         m_allDstImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1710                 }
1711         }
1712         else // bind all layers at once
1713         {
1714                 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1715                 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, numLayers);
1716
1717                 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1718                 m_allSrcImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1719                 m_allDstImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1720         }
1721
1722         return *m_descriptorSetLayout;  // not passing the ownership
1723 }
1724
1725 void ImageLoadStoreLodAMDTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1726 {
1727         const VkDevice                  device  = m_context.getDevice();
1728         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1729
1730         const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1731         const VkImageView         srcImageView  = **m_allSrcImageViews[layerNdx];
1732         const VkImageView         dstImageView  = **m_allDstImageViews[layerNdx];
1733
1734         const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1735         const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1736
1737         DescriptorSetUpdateBuilder()
1738                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1739                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1740                 .update(vk, device);
1741         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1742 }
1743
1744 void ImageLoadStoreLodAMDTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1745 {
1746         const DeviceInterface& vk = m_context.getDeviceInterface();
1747         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, m_texture.numLayers());
1748         {
1749                 const VkImageMemoryBarrier preCopyImageBarriers[] =
1750                 {
1751                         makeImageMemoryBarrier(
1752                                 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1753                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1754                                 m_imageSrc->get(), fullImageSubresourceRange),
1755                         makeImageMemoryBarrier(
1756                                 0u, VK_ACCESS_SHADER_WRITE_BIT,
1757                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1758                                 m_imageDst->get(), fullImageSubresourceRange)
1759                 };
1760
1761                 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1762                         VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1763                         m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1764
1765                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1766                         (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1767         }
1768         {
1769                 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1770                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1771                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1772                         m_imageSrc->get(), fullImageSubresourceRange);
1773
1774                 std::vector<VkBufferImageCopy> copyRegions;
1775                 VkDeviceSize bufferOffset = 0u;
1776                 for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1777                 {
1778                         const VkBufferImageCopy copyParams =
1779                         {
1780                                 bufferOffset,                                                                                                                                                                   //      VkDeviceSize                            bufferOffset;
1781                                 0u,                                                                                                                                                                                             //      deUint32                                        bufferRowLength;
1782                                 0u,                                                                                                                                                                                             //      deUint32                                        bufferImageHeight;
1783                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, m_texture.numLayers()),             //      VkImageSubresourceLayers        imageSubresource;
1784                                 makeOffset3D(0, 0, 0),                                                                                                                                                  //      VkOffset3D                                      imageOffset;
1785                                 makeExtent3D(m_texture.layerSize(levelNdx)),                                                                                                    //      VkExtent3D                                      imageExtent;
1786                         };
1787                         copyRegions.push_back(copyParams);
1788                         bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1789                 }
1790
1791                 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32) copyRegions.size(), copyRegions.data());
1792                 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);
1793         }
1794 }
1795
1796 void ImageLoadStoreLodAMDTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1797 {
1798         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1799 }
1800
1801 void ImageLoadStoreLodAMDTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1802 {
1803         commandCopyMipmapImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageFormat, m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1804 }
1805
1806 //! Load/store test for buffers
1807 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1808 {
1809 public:
1810                                                                         BufferLoadStoreTestInstance             (Context&                               context,
1811                                                                                                                                          const Texture&                 texture,
1812                                                                                                                                          const VkFormat                 format,
1813                                                                                                                                          const VkFormat                 imageFormat,
1814                                                                                                                                          const bool                             declareImageFormatInShader,
1815                                                                                                                                          const bool                             minalign,
1816                                                                                                                                          const bool                             bufferLoadUniform);
1817
1818 protected:
1819         VkDescriptorSetLayout                   prepareDescriptors                              (void);
1820         void                                                    commandAfterCompute                             (const VkCommandBuffer  cmdBuffer);
1821
1822         void                                                    commandBindDescriptorsForLayer  (const VkCommandBuffer  cmdBuffer,
1823                                                                                                                                          const VkPipelineLayout pipelineLayout,
1824                                                                                                                                          const int                              layerNdx);
1825
1826         Buffer*                                                 getResultBuffer                                 (void) const { return m_imageBufferDst.get(); }
1827
1828         de::MovePtr<Buffer>                             m_imageBufferDst;
1829         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
1830         Move<VkDescriptorPool>                  m_descriptorPool;
1831         Move<VkDescriptorSet>                   m_descriptorSet;
1832         Move<VkBufferView>                              m_bufferViewSrc;
1833         Move<VkBufferView>                              m_bufferViewDst;
1834 };
1835
1836 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context&                      context,
1837                                                                                                                   const Texture&        texture,
1838                                                                                                                   const VkFormat        format,
1839                                                                                                                   const VkFormat        imageFormat,
1840                                                                                                                   const bool            declareImageFormatInShader,
1841                                                                                                                   const bool            minalign,
1842                                                                                                                   const bool            bufferLoadUniform)
1843         : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false, minalign, bufferLoadUniform)
1844 {
1845         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1846         const VkDevice                  device          = m_context.getDevice();
1847         Allocator&                              allocator       = m_context.getDefaultAllocator();
1848
1849         // Create a destination buffer.
1850
1851         m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1852                 vk, device, allocator,
1853                 makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1854                 MemoryRequirement::HostVisible));
1855 }
1856
1857 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1858 {
1859         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1860         const VkDevice                  device  = m_context.getDevice();
1861
1862         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1863                 .addSingleBinding(m_bufferLoadDescriptorType, VK_SHADER_STAGE_COMPUTE_BIT)
1864                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1865                 .build(vk, device);
1866
1867         m_descriptorPool = DescriptorPoolBuilder()
1868                 .addType(m_bufferLoadDescriptorType)
1869                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1870                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1871
1872         VkFormat dstFormat = formatHasThreeComponents(m_format) ? getSingleComponentFormat(m_format) : m_format;
1873
1874         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1875         m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_srcViewOffset, m_imageSizeBytes);
1876         m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), dstFormat, m_dstViewOffset, m_imageSizeBytes);
1877
1878         return *m_descriptorSetLayout;  // not passing the ownership
1879 }
1880
1881 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1882 {
1883         DE_ASSERT(layerNdx == 0);
1884         DE_UNREF(layerNdx);
1885
1886         const VkDevice                  device  = m_context.getDevice();
1887         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1888
1889         DescriptorSetUpdateBuilder()
1890                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), m_bufferLoadDescriptorType, &m_bufferViewSrc.get())
1891                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1892                 .update(vk, device);
1893         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1894 }
1895
1896 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1897 {
1898         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes + m_dstViewOffset);
1899 }
1900
1901 TestInstance* StoreTest::createInstance (Context& context) const
1902 {
1903         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1904                 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_minalign);
1905         else
1906                 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind, m_minalign);
1907 }
1908
1909 TestInstance* LoadStoreTest::createInstance (Context& context) const
1910 {
1911         if (m_imageLoadStoreLodAMD)
1912                 return new ImageLoadStoreLodAMDTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
1913
1914         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1915                 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_minalign, m_bufferLoadUniform);
1916         else
1917                 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
1918 }
1919
1920 class ImageExtendOperandTestInstance : public BaseTestInstance
1921 {
1922 public:
1923                                                                         ImageExtendOperandTestInstance                  (Context&                               context,
1924                                                                                                                                                          const Texture&                 texture,
1925                                                                                                                                                          const VkFormat                 readFormat,
1926                                                                                                                                                          const VkFormat                 writeFormat,
1927                                                                                                                                                          bool                                   relaxedPrecision);
1928
1929         virtual                                                 ~ImageExtendOperandTestInstance                 (void) {}
1930
1931 protected:
1932
1933         VkDescriptorSetLayout                   prepareDescriptors                                              (void);
1934         void                                                    commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer);
1935         void                                                    commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer);
1936         void                                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
1937
1938         void                                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
1939                                                                                                                                                          const VkPipelineLayout pipelineLayout,
1940                                                                                                                                                          const int                              layerNdx);
1941
1942         tcu::TestStatus                                 verifyResult                                                    (void);
1943
1944 protected:
1945
1946         bool                                                    m_isSigned;
1947         tcu::TextureLevel                               m_inputImageData;
1948
1949         de::MovePtr<Image>                              m_imageSrc;                             // source image
1950         SharedVkImageView                               m_imageSrcView;
1951         VkDeviceSize                                    m_imageSrcSize;
1952
1953         de::MovePtr<Image>                              m_imageDst;                             // dest image
1954         SharedVkImageView                               m_imageDstView;
1955         VkFormat                                                m_imageDstFormat;
1956         VkDeviceSize                                    m_imageDstSize;
1957
1958         de::MovePtr<Buffer>                             m_buffer;                               // result buffer
1959
1960         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
1961         Move<VkDescriptorPool>                  m_descriptorPool;
1962         SharedVkDescriptorSet                   m_descriptorSet;
1963
1964         bool                                                    m_relaxedPrecision;
1965 };
1966
1967 ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context,
1968                                                                                                                                 const Texture& texture,
1969                                                                                                                                 const VkFormat readFormat,
1970                                                                                                                                 const VkFormat writeFormat,
1971                                                                                                                                 bool relaxedPrecision)
1972         : BaseTestInstance              (context, texture, readFormat, true, true, false, false)
1973         , m_imageDstFormat              (writeFormat)
1974         , m_relaxedPrecision    (relaxedPrecision)
1975 {
1976         const DeviceInterface&          vk                              = m_context.getDeviceInterface();
1977         const VkDevice                          device                  = m_context.getDevice();
1978         Allocator&                                      allocator               = m_context.getDefaultAllocator();
1979         const deInt32                           width                   = texture.size().x();
1980         const deInt32                           height                  = texture.size().y();
1981         const tcu::TextureFormat        textureFormat   = mapVkFormat(m_format);
1982
1983         // Generate reference image
1984         m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
1985         m_inputImageData.setStorage(textureFormat, width, height, 1);
1986
1987         const tcu::PixelBufferAccess    access          = m_inputImageData.getAccess();
1988         const int                                               valueStart      = (m_isSigned ? (-width / 2) : 0);
1989
1990         for (int x = 0; x < width; ++x)
1991         for (int y = 0; y < height; ++y)
1992         {
1993                 const tcu::IVec4 color(valueStart + x, valueStart + y, valueStart, valueStart);
1994                 access.setPixel(color, x, y);
1995         }
1996
1997         // Create source image
1998         m_imageSrc = de::MovePtr<Image>(new Image(
1999                 vk, device, allocator,
2000                 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u),
2001                 MemoryRequirement::Any));
2002
2003         // Create destination image
2004         m_imageDst = de::MovePtr<Image>(new Image(
2005                 vk, device, allocator,
2006                 makeImageCreateInfo(m_texture, m_imageDstFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
2007                 MemoryRequirement::Any));
2008
2009         // Compute image and buffer sizes
2010         m_imageSrcSize                                  = width * height * tcu::getPixelSize(textureFormat);
2011         m_imageDstSize                                  = width * height * tcu::getPixelSize(mapVkFormat(m_imageDstFormat));
2012         VkDeviceSize bufferSizeBytes    = de::max(m_imageSrcSize, m_imageDstSize);
2013
2014         // Create helper buffer able to store input data and image write result
2015         m_buffer = de::MovePtr<Buffer>(new Buffer(
2016                 vk, device, allocator,
2017                 makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2018                 MemoryRequirement::HostVisible));
2019
2020         const Allocation& alloc = m_buffer->getAllocation();
2021         deMemcpy(alloc.getHostPtr(), m_inputImageData.getAccess().getDataPtr(), static_cast<size_t>(m_imageSrcSize));
2022         flushAlloc(vk, device, alloc);
2023 }
2024
2025 VkDescriptorSetLayout ImageExtendOperandTestInstance::prepareDescriptors (void)
2026 {
2027         const DeviceInterface&  vk              = m_context.getDeviceInterface();
2028         const VkDevice                  device  = m_context.getDevice();
2029
2030         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2031                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2032                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2033                 .build(vk, device);
2034
2035         m_descriptorPool = DescriptorPoolBuilder()
2036                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2037                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2038                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
2039
2040         const VkImageViewType viewType = mapImageViewType(m_texture.type());
2041         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2042
2043         m_descriptorSet = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2044         m_imageSrcView  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2045         m_imageDstView  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_imageDstFormat, subresourceRange));
2046
2047         return *m_descriptorSetLayout;  // not passing the ownership
2048 }
2049
2050 void ImageExtendOperandTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2051 {
2052         DE_UNREF(layerNdx);
2053
2054         const DeviceInterface&  vk                              = m_context.getDeviceInterface();
2055         const VkDevice                  device                  = m_context.getDevice();
2056         const VkDescriptorSet   descriptorSet   = **m_descriptorSet;
2057
2058         const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageSrcView, VK_IMAGE_LAYOUT_GENERAL);
2059         const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageDstView, VK_IMAGE_LAYOUT_GENERAL);
2060
2061         typedef DescriptorSetUpdateBuilder::Location DSUBL;
2062         DescriptorSetUpdateBuilder()
2063                 .writeSingle(descriptorSet, DSUBL::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
2064                 .writeSingle(descriptorSet, DSUBL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
2065                 .update(vk, device);
2066         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2067 }
2068
2069 void ImageExtendOperandTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
2070 {
2071         const DeviceInterface& vk = m_context.getDeviceInterface();
2072
2073         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
2074         {
2075                 const VkImageMemoryBarrier preCopyImageBarriers[] =
2076                 {
2077                         makeImageMemoryBarrier(
2078                                 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2079                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2080                                 m_imageSrc->get(), fullImageSubresourceRange),
2081                         makeImageMemoryBarrier(
2082                                 0u, VK_ACCESS_SHADER_WRITE_BIT,
2083                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2084                                 m_imageDst->get(), fullImageSubresourceRange)
2085                 };
2086
2087                 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
2088                         VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2089                         m_buffer->get(), 0ull, m_imageSrcSize);
2090
2091                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2092                         (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2093         }
2094         {
2095                 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2096                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
2097                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2098                         m_imageSrc->get(), fullImageSubresourceRange);
2099
2100                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
2101
2102                 vk.cmdCopyBufferToImage(cmdBuffer, m_buffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
2103                 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);
2104         }
2105 }
2106
2107 void ImageExtendOperandTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
2108 {
2109         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2110 }
2111
2112 void ImageExtendOperandTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2113 {
2114         commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
2115 }
2116
2117 // Clears the high bits of every pixel in the pixel buffer, leaving only the lowest 16 bits of each component.
2118 void clearHighBits (const tcu::PixelBufferAccess& pixels, int width, int height)
2119 {
2120         for (int y = 0; y < height; ++y)
2121         for (int x = 0; x < width; ++x)
2122         {
2123                 auto color = pixels.getPixelUint(x, y);
2124                 for (int c = 0; c < decltype(color)::SIZE; ++c)
2125                         color[c] &= 0xFFFFull;
2126                 pixels.setPixel(color, x, y);
2127         }
2128 }
2129
2130 tcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
2131 {
2132         const DeviceInterface&                  vk                      = m_context.getDeviceInterface();
2133         const VkDevice                                  device          = m_context.getDevice();
2134         const tcu::IVec3                                imageSize       = m_texture.size();
2135         const tcu::PixelBufferAccess    inputAccess     = m_inputImageData.getAccess();
2136         const deInt32                                   width           = inputAccess.getWidth();
2137         const deInt32                                   height          = inputAccess.getHeight();
2138         tcu::TextureLevel                               refImage        (mapVkFormat(m_imageDstFormat), width, height);
2139         tcu::PixelBufferAccess                  refAccess       = refImage.getAccess();
2140
2141         for (int x = 0; x < width; ++x)
2142         for (int y = 0; y < height; ++y)
2143         {
2144                 tcu::IVec4 color = inputAccess.getPixelInt(x, y);
2145                 refAccess.setPixel(color, x, y);
2146         }
2147
2148         const Allocation& alloc = m_buffer->getAllocation();
2149         invalidateAlloc(vk, device, alloc);
2150         const tcu::PixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
2151
2152         if (m_relaxedPrecision)
2153         {
2154                 // Preserve the lowest 16 bits of the reference and result pixels only.
2155                 clearHighBits(refAccess, width, height);
2156                 clearHighBits(result, width, height);
2157         }
2158
2159         if (tcu::intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT, true/*use64Bits*/))
2160                 return tcu::TestStatus::pass("Passed");
2161         else
2162                 return tcu::TestStatus::fail("Image comparison failed");
2163 }
2164
2165 enum class ExtendTestType
2166 {
2167         READ  = 0,
2168         WRITE = 1,
2169 };
2170
2171 enum class ExtendOperand
2172 {
2173         SIGN_EXTEND = 0,
2174         ZERO_EXTEND = 1
2175 };
2176
2177 class ImageExtendOperandTest : public TestCase
2178 {
2179 public:
2180                                                         ImageExtendOperandTest  (tcu::TestContext&                                      testCtx,
2181                                                                                                          const std::string&                                     name,
2182                                                                                                          const Texture                                          texture,
2183                                                                                                          const VkFormat                                         readFormat,
2184                                                                                                          const VkFormat                                         writeFormat,
2185                                                                                                          const bool                                                     signedInt,
2186                                                                                                          const bool                                                     relaxedPrecision,
2187                                                                                                          ExtendTestType                                         extendTestType);
2188
2189         void                                    checkSupport                    (Context&                               context) const;
2190         void                                    initPrograms                    (SourceCollections&             programCollection) const;
2191         TestInstance*                   createInstance                  (Context&                               context) const;
2192
2193 private:
2194         bool                                    isWriteTest                             () const { return (m_extendTestType == ExtendTestType::WRITE); }
2195
2196         const Texture                   m_texture;
2197         VkFormat                                m_readFormat;
2198         VkFormat                                m_writeFormat;
2199         bool                                    m_operandForce;                 // Use an operand that doesn't match SampledType?
2200         bool                                    m_relaxedPrecision;
2201         ExtendTestType                  m_extendTestType;
2202 };
2203
2204 ImageExtendOperandTest::ImageExtendOperandTest (tcu::TestContext&                               testCtx,
2205                                                                                                 const std::string&                              name,
2206                                                                                                 const Texture                                   texture,
2207                                                                                                 const VkFormat                                  readFormat,
2208                                                                                                 const VkFormat                                  writeFormat,
2209                                                                                                 const bool                                              operandForce,
2210                                                                                                 const bool                                              relaxedPrecision,
2211                                                                                                 ExtendTestType                                  extendTestType)
2212         : TestCase                                              (testCtx, name, "")
2213         , m_texture                                             (texture)
2214         , m_readFormat                                  (readFormat)
2215         , m_writeFormat                                 (writeFormat)
2216         , m_operandForce                                (operandForce)
2217         , m_relaxedPrecision                    (relaxedPrecision)
2218         , m_extendTestType                              (extendTestType)
2219 {
2220 }
2221
2222 void checkFormatProperties (Context& context, VkFormat format)
2223 {
2224         const VkFormatProperties3KHR formatProperties (context.getFormatProperties(format));
2225
2226         if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2227                 TCU_THROW(NotSupportedError, "Format not supported for storage images");
2228 }
2229
2230 void check64BitSupportIfNeeded (Context& context, VkFormat readFormat, VkFormat writeFormat)
2231 {
2232         if (is64BitIntegerFormat(readFormat) || is64BitIntegerFormat(writeFormat))
2233         {
2234                 const auto& features = context.getDeviceFeatures();
2235                 if (!features.shaderInt64)
2236                         TCU_THROW(NotSupportedError, "64-bit integers not supported in shaders");
2237         }
2238 }
2239
2240 void ImageExtendOperandTest::checkSupport (Context& context) const
2241 {
2242         if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
2243                 TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
2244
2245         check64BitSupportIfNeeded(context, m_readFormat, m_writeFormat);
2246
2247         checkFormatProperties(context, m_readFormat);
2248         checkFormatProperties(context, m_writeFormat);
2249 }
2250
2251 void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection) const
2252 {
2253         tcu::StringTemplate shaderTemplate(
2254                 "OpCapability Shader\n"
2255                 "OpCapability StorageImageExtendedFormats\n"
2256
2257                 "${capability}"
2258                 "${extension}"
2259
2260                 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2261                 "OpMemoryModel Logical GLSL450\n"
2262                 "OpEntryPoint GLCompute %main \"main\" %id %src_image_ptr %dst_image_ptr\n"
2263                 "OpExecutionMode %main LocalSize 1 1 1\n"
2264
2265                 // decorations
2266                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2267
2268                 "OpDecorate %src_image_ptr DescriptorSet 0\n"
2269                 "OpDecorate %src_image_ptr Binding 0\n"
2270                 "OpDecorate %src_image_ptr NonWritable\n"
2271
2272                 "${relaxed_precision}"
2273
2274                 "OpDecorate %dst_image_ptr DescriptorSet 0\n"
2275                 "OpDecorate %dst_image_ptr Binding 1\n"
2276                 "OpDecorate %dst_image_ptr NonReadable\n"
2277
2278                 // types
2279                 "%type_void                          = OpTypeVoid\n"
2280                 "%type_i32                           = OpTypeInt 32 1\n"
2281                 "%type_u32                           = OpTypeInt 32 0\n"
2282                 "%type_vec2_i32                      = OpTypeVector %type_i32 2\n"
2283                 "%type_vec2_u32                      = OpTypeVector %type_u32 2\n"
2284                 "%type_vec3_i32                      = OpTypeVector %type_i32 3\n"
2285                 "%type_vec3_u32                      = OpTypeVector %type_u32 3\n"
2286                 "%type_vec4_i32                      = OpTypeVector %type_i32 4\n"
2287                 "%type_vec4_u32                      = OpTypeVector %type_u32 4\n"
2288                 "${extra_types}"
2289
2290                 "%type_fun_void                      = OpTypeFunction %type_void\n"
2291
2292                 "${image_types}"
2293
2294                 "%type_ptr_in_vec3_u32               = OpTypePointer Input %type_vec3_u32\n"
2295                 "%type_ptr_in_u32                    = OpTypePointer Input %type_u32\n"
2296
2297                 "${image_uniforms}"
2298
2299                 // variables
2300                 "%id                                 = OpVariable %type_ptr_in_vec3_u32 Input\n"
2301
2302                 "${image_variables}"
2303
2304                 // main function
2305                 "%main                               = OpFunction %type_void None %type_fun_void\n"
2306                 "%label                              = OpLabel\n"
2307
2308                 "${image_load}"
2309
2310                 "%idvec                              = OpLoad %type_vec3_u32 %id\n"
2311                 "%id_xy                              = OpVectorShuffle %type_vec2_u32 %idvec %idvec 0 1\n"
2312                 "%coord                              = OpBitcast %type_vec2_i32 %id_xy\n"
2313                 "%value                              = OpImageRead ${sampled_type_vec4} %src_image %coord ${read_extend_operand}\n"
2314                 "                                      OpImageWrite %dst_image %coord %value ${write_extend_operand}\n"
2315                 "                                      OpReturn\n"
2316                 "                                      OpFunctionEnd\n");
2317
2318         const auto      testedFormat    = mapVkFormat(isWriteTest() ? m_writeFormat : m_readFormat);
2319         const bool      isSigned                = (getTextureChannelClass(testedFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2320
2321         const auto isRead64             = is64BitIntegerFormat(m_readFormat);
2322         const auto isWrite64    = is64BitIntegerFormat(m_writeFormat);
2323         DE_ASSERT(isRead64 == isWrite64);
2324
2325         const bool using64Bits                          = (isRead64 || isWrite64);
2326
2327         // Additional capabilities when needed.
2328         std::string capability;
2329         std::string extension;
2330         std::string extraTypes;
2331
2332         if (using64Bits)
2333         {
2334                         extension  += "OpExtension \"SPV_EXT_shader_image_int64\"\n";
2335                         capability +=
2336                                 "OpCapability Int64\n"
2337                                 "OpCapability Int64ImageEXT\n"
2338                                 ;
2339                         extraTypes +=
2340                                 "%type_i64                           = OpTypeInt 64 1\n"
2341                                 "%type_u64                           = OpTypeInt 64 0\n"
2342                                 "%type_vec3_i64                      = OpTypeVector %type_i64 3\n"
2343                                 "%type_vec3_u64                      = OpTypeVector %type_u64 3\n"
2344                                 "%type_vec4_i64                      = OpTypeVector %type_i64 4\n"
2345                                 "%type_vec4_u64                      = OpTypeVector %type_u64 4\n"
2346                                 ;
2347         }
2348
2349         std::string relaxed = "";
2350         if (m_relaxedPrecision)
2351                 relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
2352
2353         // Sampled type depends on the format sign and mismatch force flag.
2354         const bool                      signedSampleType        = ((isSigned && !m_operandForce) || (!isSigned && m_operandForce));
2355         const std::string       bits                            = (using64Bits ? "64" : "32");
2356         const std::string       sampledTypePostfix      = (signedSampleType ? "i" : "u") + bits;
2357         const std::string       extendOperandStr        = (isSigned ? "SignExtend" : "ZeroExtend");
2358
2359         std::map<std::string, std::string> specializations =
2360         {
2361                 { "image_type_id",                      "%type_image" },
2362                 { "image_uni_ptr_type_id",      "%type_ptr_uniform_const_image" },
2363                 { "image_var_id",                       "%src_image_ptr" },
2364                 { "image_id",                           "%src_image" },
2365                 { "capability",                         capability },
2366                 { "extension",                          extension },
2367                 { "extra_types",                        extraTypes },
2368                 { "relaxed_precision",          relaxed },
2369                 { "image_format",                       getSpirvFormat(m_readFormat) },
2370                 { "sampled_type",                       (std::string("%type_") + sampledTypePostfix) },
2371                 { "sampled_type_vec4",          (std::string("%type_vec4_") + sampledTypePostfix) },
2372                 { "read_extend_operand",        (!isWriteTest() ? extendOperandStr : "") },
2373                 { "write_extend_operand",       (isWriteTest()  ? extendOperandStr : "") },
2374         };
2375
2376         // Addidtional parametrization is needed for a case when source and destination textures have same format
2377         tcu::StringTemplate imageTypeTemplate(
2378                 "${image_type_id}                     = OpTypeImage ${sampled_type} 2D 0 0 0 2 ${image_format}\n");
2379         tcu::StringTemplate imageUniformTypeTemplate(
2380                 "${image_uni_ptr_type_id}   = OpTypePointer UniformConstant ${image_type_id}\n");
2381         tcu::StringTemplate imageVariablesTemplate(
2382                 "${image_var_id}                      = OpVariable ${image_uni_ptr_type_id} UniformConstant\n");
2383         tcu::StringTemplate imageLoadTemplate(
2384                 "${image_id}                          = OpLoad ${image_type_id} ${image_var_id}\n");
2385
2386         std::string imageTypes;
2387         std::string imageUniformTypes;
2388         std::string imageVariables;
2389         std::string imageLoad;
2390
2391         // If input image format is the same as output there is less spir-v definitions
2392         if (m_readFormat == m_writeFormat)
2393         {
2394                 imageTypes                      = imageTypeTemplate.specialize(specializations);
2395                 imageUniformTypes       = imageUniformTypeTemplate.specialize(specializations);
2396                 imageVariables          = imageVariablesTemplate.specialize(specializations);
2397                 imageLoad                       = imageLoadTemplate.specialize(specializations);
2398
2399                 specializations["image_var_id"]                         = "%dst_image_ptr";
2400                 specializations["image_id"]                                     = "%dst_image";
2401                 imageVariables          += imageVariablesTemplate.specialize(specializations);
2402                 imageLoad                       += imageLoadTemplate.specialize(specializations);
2403         }
2404         else
2405         {
2406                 specializations["image_type_id"]                        = "%type_src_image";
2407                 specializations["image_uni_ptr_type_id"]        = "%type_ptr_uniform_const_src_image";
2408                 imageTypes                      = imageTypeTemplate.specialize(specializations);
2409                 imageUniformTypes       = imageUniformTypeTemplate.specialize(specializations);
2410                 imageVariables          = imageVariablesTemplate.specialize(specializations);
2411                 imageLoad                       = imageLoadTemplate.specialize(specializations);
2412
2413                 specializations["image_format"]                         = getSpirvFormat(m_writeFormat);
2414                 specializations["image_type_id"]                        = "%type_dst_image";
2415                 specializations["image_uni_ptr_type_id"]        = "%type_ptr_uniform_const_dst_image";
2416                 specializations["image_var_id"]                         = "%dst_image_ptr";
2417                 specializations["image_id"]                                     = "%dst_image";
2418                 imageTypes                      += imageTypeTemplate.specialize(specializations);
2419                 imageUniformTypes       += imageUniformTypeTemplate.specialize(specializations);
2420                 imageVariables          += imageVariablesTemplate.specialize(specializations);
2421                 imageLoad                       += imageLoadTemplate.specialize(specializations);
2422         }
2423
2424         specializations["image_types"]          = imageTypes;
2425         specializations["image_uniforms"]       = imageUniformTypes;
2426         specializations["image_variables"]      = imageVariables;
2427         specializations["image_load"]           = imageLoad;
2428
2429         // Specialize whole shader and add it to program collection
2430         programCollection.spirvAsmSources.add("comp") << shaderTemplate.specialize(specializations)
2431                 << vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
2432 }
2433
2434 TestInstance* ImageExtendOperandTest::createInstance(Context& context) const
2435 {
2436         return new ImageExtendOperandTestInstance(context, m_texture, m_readFormat, m_writeFormat, m_relaxedPrecision);
2437 }
2438
2439 static const Texture s_textures[] =
2440 {
2441         Texture(IMAGE_TYPE_1D,                  tcu::IVec3(64,  1,      1),     1),
2442         Texture(IMAGE_TYPE_1D_ARRAY,    tcu::IVec3(64,  1,      1),     8),
2443         Texture(IMAGE_TYPE_2D,                  tcu::IVec3(64,  64,     1),     1),
2444         Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(64,  64,     1),     8),
2445         Texture(IMAGE_TYPE_3D,                  tcu::IVec3(64,  64,     8),     1),
2446         Texture(IMAGE_TYPE_CUBE,                tcu::IVec3(64,  64,     1),     6),
2447         Texture(IMAGE_TYPE_CUBE_ARRAY,  tcu::IVec3(64,  64,     1),     2*6),
2448         Texture(IMAGE_TYPE_BUFFER,              tcu::IVec3(64,  1,      1),     1),
2449 };
2450
2451 const Texture& getTestTexture (const ImageType imageType)
2452 {
2453         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2454                 if (s_textures[textureNdx].type() == imageType)
2455                         return s_textures[textureNdx];
2456
2457         DE_FATAL("Internal error");
2458         return s_textures[0];
2459 }
2460
2461 static const VkFormat s_formats[] =
2462 {
2463         VK_FORMAT_R32G32B32A32_SFLOAT,
2464         VK_FORMAT_R16G16B16A16_SFLOAT,
2465         VK_FORMAT_R32_SFLOAT,
2466
2467         VK_FORMAT_R32G32B32A32_UINT,
2468         VK_FORMAT_R16G16B16A16_UINT,
2469         VK_FORMAT_R8G8B8A8_UINT,
2470         VK_FORMAT_R32_UINT,
2471
2472         VK_FORMAT_R32G32B32A32_SINT,
2473         VK_FORMAT_R16G16B16A16_SINT,
2474         VK_FORMAT_R8G8B8A8_SINT,
2475         VK_FORMAT_R32_SINT,
2476
2477         VK_FORMAT_R8G8B8A8_UNORM,
2478
2479         VK_FORMAT_B8G8R8A8_UNORM,
2480         VK_FORMAT_B8G8R8A8_UINT,
2481
2482         VK_FORMAT_R8G8B8A8_SNORM,
2483
2484         VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2485
2486         VK_FORMAT_R32G32_SFLOAT,
2487         VK_FORMAT_R16G16_SFLOAT,
2488         VK_FORMAT_R16_SFLOAT,
2489
2490         VK_FORMAT_A2B10G10R10_UINT_PACK32,
2491         VK_FORMAT_R32G32_UINT,
2492         VK_FORMAT_R16G16_UINT,
2493         VK_FORMAT_R16_UINT,
2494         VK_FORMAT_R8G8_UINT,
2495         VK_FORMAT_R8_UINT,
2496
2497         VK_FORMAT_R32G32_SINT,
2498         VK_FORMAT_R16G16_SINT,
2499         VK_FORMAT_R16_SINT,
2500         VK_FORMAT_R8G8_SINT,
2501         VK_FORMAT_R8_SINT,
2502
2503         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2504         VK_FORMAT_R16G16B16A16_UNORM,
2505         VK_FORMAT_R16G16B16A16_SNORM,
2506         VK_FORMAT_R16G16_UNORM,
2507         VK_FORMAT_R16_UNORM,
2508         VK_FORMAT_R8G8_UNORM,
2509         VK_FORMAT_R8_UNORM,
2510
2511         VK_FORMAT_R16G16_SNORM,
2512         VK_FORMAT_R16_SNORM,
2513         VK_FORMAT_R8G8_SNORM,
2514         VK_FORMAT_R8_SNORM
2515 };
2516
2517 static const VkFormat s_formatsThreeComponent[] =
2518 {
2519         VK_FORMAT_R8G8B8_UINT,
2520         VK_FORMAT_R8G8B8_SINT,
2521         VK_FORMAT_R8G8B8_UNORM,
2522         VK_FORMAT_R8G8B8_SNORM,
2523         VK_FORMAT_R16G16B16_UINT,
2524         VK_FORMAT_R16G16B16_SINT,
2525         VK_FORMAT_R16G16B16_UNORM,
2526         VK_FORMAT_R16G16B16_SNORM,
2527         VK_FORMAT_R16G16B16_SFLOAT,
2528         VK_FORMAT_R32G32B32_UINT,
2529         VK_FORMAT_R32G32B32_SINT,
2530         VK_FORMAT_R32G32B32_SFLOAT,
2531 };
2532
2533 } // anonymous ns
2534
2535 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
2536 {
2537         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
2538         de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
2539         de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
2540
2541         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2542         {
2543                 const Texture& texture = s_textures[textureNdx];
2544                 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2545                 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2546                 const bool isLayered = (texture.numLayers() > 1);
2547
2548                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2549                 {
2550                         const bool hasSpirvFmt = hasSpirvFormat(s_formats[formatNdx]);
2551
2552                         if (hasSpirvFmt)
2553                                 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
2554                         groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
2555
2556                         if (isLayered && hasSpirvFmt)
2557                                 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2558                                                                                                                  texture, s_formats[formatNdx],
2559                                                                                                                  StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2560
2561                         if (texture.type() == IMAGE_TYPE_BUFFER)
2562                         {
2563                                 if (hasSpirvFmt)
2564                                         groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2565                                 groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN));
2566                         }
2567                 }
2568
2569                 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2570                 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2571         }
2572
2573         testGroup->addChild(testGroupWithFormat.release());
2574         testGroup->addChild(testGroupWithoutFormat.release());
2575
2576         return testGroup.release();
2577 }
2578
2579 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
2580 {
2581         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
2582         de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2583         de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2584
2585         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2586         {
2587                 const Texture& texture = s_textures[textureNdx];
2588                 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2589                 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2590                 const bool isLayered = (texture.numLayers() > 1);
2591
2592                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2593                 {
2594                         // These tests always require a SPIR-V format for the write image, even if the read
2595                         // image is being used without a format.
2596                         if (!hasSpirvFormat(s_formats[formatNdx]))
2597                                 continue;
2598
2599                         groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
2600                         groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
2601
2602                         if (isLayered)
2603                                 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2604                                                                                                                  texture, s_formats[formatNdx], s_formats[formatNdx],
2605                                                                                                                  LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2606                         if (texture.type() == IMAGE_TYPE_BUFFER)
2607                         {
2608                                 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2609                                 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign_uniform", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2610                                 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN));
2611                                 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign_uniform", "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2612                         }
2613                 }
2614
2615                 if (texture.type() == IMAGE_TYPE_BUFFER)
2616                 {
2617                         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formatsThreeComponent); ++formatNdx)
2618                         {
2619                                 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formatsThreeComponent[formatNdx]) + "_uniform", "", texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2620                                 groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formatsThreeComponent[formatNdx]) + "_minalign_uniform", "", texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2621                         }
2622                 }
2623
2624                 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2625                 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2626         }
2627
2628         testGroup->addChild(testGroupWithFormat.release());
2629         testGroup->addChild(testGroupWithoutFormat.release());
2630
2631         return testGroup.release();
2632 }
2633
2634 tcu::TestCaseGroup* createImageLoadStoreLodAMDTests (tcu::TestContext& testCtx)
2635 {
2636         static const Texture textures[] =
2637         {
2638                 Texture(IMAGE_TYPE_1D_ARRAY,    tcu::IVec3(64,  1,      1),     8, 1, 6),
2639                 Texture(IMAGE_TYPE_1D,                  tcu::IVec3(64,  1,      1),     1, 1, 6),
2640                 Texture(IMAGE_TYPE_2D,                  tcu::IVec3(64,  64,     1),     1, 1, 6),
2641                 Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(64,  64,     1),     8, 1, 6),
2642                 Texture(IMAGE_TYPE_3D,                  tcu::IVec3(64,  64,     8),     1, 1, 6),
2643                 Texture(IMAGE_TYPE_CUBE,                tcu::IVec3(64,  64,     1),     6, 1, 6),
2644                 Texture(IMAGE_TYPE_CUBE_ARRAY,  tcu::IVec3(64,  64,     1),     2*6, 1, 6),
2645         };
2646
2647         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_lod", "Cases with imageLoad() followed by imageStore()"));
2648         de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2649         de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2650
2651         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(textures); ++textureNdx)
2652         {
2653                 const Texture& texture = textures[textureNdx];
2654                 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2655                 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2656                 const bool isLayered = (texture.numLayers() > 1);
2657
2658                 if (texture.type() == IMAGE_TYPE_BUFFER)
2659                         continue;
2660
2661                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2662                 {
2663                         // These tests always require a SPIR-V format for the write image, even if the read
2664                         // image is being used without a format.
2665                         if (!hasSpirvFormat(s_formats[formatNdx]))
2666                                 continue;
2667
2668                         groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
2669                         groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0, DE_TRUE));
2670
2671                         if (isLayered)
2672                                 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
2673                                                                                                                  texture, s_formats[formatNdx], s_formats[formatNdx],
2674                                                                                                                  LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
2675                 }
2676
2677                 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2678                 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2679         }
2680
2681         testGroup->addChild(testGroupWithFormat.release());
2682         testGroup->addChild(testGroupWithoutFormat.release());
2683
2684         return testGroup.release();
2685 }
2686
2687 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
2688 {
2689         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
2690
2691         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2692         {
2693                 const Texture& texture = s_textures[textureNdx];
2694                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
2695
2696                 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
2697                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2698                 {
2699                         if (!hasSpirvFormat(s_formats[formatNdx]))
2700                                 continue;
2701
2702                         const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
2703                         if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
2704                                 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
2705                 }
2706                 testGroup->addChild(groupByImageViewType.release());
2707         }
2708
2709         return testGroup.release();
2710 }
2711
2712 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
2713 {
2714         const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
2715         const Texture& texture = getTestTexture(imageType);
2716         return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2717 }
2718
2719 namespace
2720 {
2721
2722 bool relaxedOK(VkFormat format)
2723 {
2724         tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
2725         int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
2726         return maxBitDepth <= 16;
2727 }
2728
2729 // Get a format used for reading or writing in extension operand tests. These formats allow representing the shader sampled type to
2730 // verify results from read or write operations.
2731 VkFormat getShaderExtensionOperandFormat (bool isSigned, bool is64Bit)
2732 {
2733         const VkFormat formats[] =
2734         {
2735                 VK_FORMAT_R32G32B32A32_UINT,
2736                 VK_FORMAT_R32G32B32A32_SINT,
2737                 VK_FORMAT_R64_UINT,
2738                 VK_FORMAT_R64_SINT,
2739         };
2740         return formats[2u * (is64Bit ? 1u : 0u) + (isSigned ? 1u : 0u)];
2741 }
2742
2743 // INT or UINT format?
2744 bool isIntegralFormat (VkFormat format)
2745 {
2746         return (isIntFormat(format) || isUintFormat(format));
2747 }
2748
2749 // Return the list of formats used for the extension operand tests (SignExten/ZeroExtend).
2750 std::vector<VkFormat> getExtensionOperandFormatList (void)
2751 {
2752         std::vector<VkFormat> formatList;
2753
2754         for (auto format : s_formats)
2755         {
2756                 if (isIntegralFormat(format))
2757                         formatList.push_back(format);
2758         }
2759
2760         formatList.push_back(VK_FORMAT_R64_SINT);
2761         formatList.push_back(VK_FORMAT_R64_UINT);
2762
2763         return formatList;
2764 }
2765
2766 } // anonymous
2767
2768 tcu::TestCaseGroup* createImageExtendOperandsTests(tcu::TestContext& testCtx)
2769 {
2770         using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2771
2772         GroupPtr testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
2773
2774         const struct
2775         {
2776                 ExtendTestType  testType;
2777                 const char*             name;
2778         } testTypes[] =
2779         {
2780                 { ExtendTestType::READ,         "read"  },
2781                 { ExtendTestType::WRITE,        "write" },
2782         };
2783
2784         const auto texture              = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
2785         const auto formatList   = getExtensionOperandFormatList();
2786
2787         for (const auto format : formatList)
2788         {
2789                 const auto isInt                = isIntFormat(format);
2790                 const auto isUint               = isUintFormat(format);
2791                 const auto use64Bits    = is64BitIntegerFormat(format);
2792
2793                 DE_ASSERT(isInt || isUint);
2794
2795                 GroupPtr formatGroup (new tcu::TestCaseGroup(testCtx, getFormatShortString(format).c_str(), ""));
2796
2797                 for (const auto& testType : testTypes)
2798                 {
2799                         GroupPtr testTypeGroup (new tcu::TestCaseGroup(testCtx, testType.name, ""));
2800
2801                         for (int match = 0; match < 2; ++match)
2802                         {
2803                                 const bool      mismatched              = (match == 1);
2804                                 const char*     matchGroupName  = (mismatched ? "mismatched_sign" : "matched_sign");
2805
2806                                 // SPIR-V does not allow this kind of sampled type override.
2807                                 if (mismatched && isUint)
2808                                         continue;
2809
2810                                 GroupPtr matchGroup (new tcu::TestCaseGroup(testCtx, matchGroupName, ""));
2811
2812                                 for (int prec = 0; prec < 2; prec++)
2813                                 {
2814                                         const bool relaxedPrecision = (prec != 0);
2815
2816                                         const char* precisionName       = (relaxedPrecision ? "relaxed_precision" : "normal_precision");
2817                                         const auto  signedOther         = ((isInt && !mismatched) || (isUint && mismatched));
2818                                         const auto      otherFormat             = getShaderExtensionOperandFormat(signedOther, use64Bits);
2819                                         const auto  readFormat          = (testType.testType == ExtendTestType::READ ?  format : otherFormat);
2820                                         const auto  writeFormat         = (testType.testType == ExtendTestType::WRITE ? format : otherFormat);
2821
2822                                         if (relaxedPrecision && !relaxedOK(readFormat))
2823                                                 continue;
2824
2825                                         if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
2826                                                 continue;
2827
2828                                         matchGroup->addChild(new ImageExtendOperandTest(testCtx, precisionName, texture, readFormat, writeFormat, mismatched, relaxedPrecision, testType.testType));
2829                                 }
2830
2831                                 testTypeGroup->addChild(matchGroup.release());
2832                         }
2833
2834                         formatGroup->addChild(testTypeGroup.release());
2835                 }
2836
2837                 testGroup->addChild(formatGroup.release());
2838         }
2839
2840         return testGroup.release();
2841 }
2842
2843 } // image
2844 } // vkt