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