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