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