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