53fc5b5394545805b38be489f39994f51d055c13
[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 "vkBuilderUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
40
41 #include "deUniquePtr.hpp"
42 #include "deSharedPtr.hpp"
43 #include "deStringUtil.hpp"
44
45 #include "tcuImageCompare.hpp"
46 #include "tcuTexture.hpp"
47 #include "tcuTextureUtil.hpp"
48 #include "tcuFloat.hpp"
49
50 #include <string>
51 #include <vector>
52
53 using namespace vk;
54
55 namespace vkt
56 {
57 namespace image
58 {
59 namespace
60 {
61
62 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
63 {
64         return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
65 }
66
67 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
68 {
69         switch (texture.type())
70         {
71                 case IMAGE_TYPE_1D:
72                 case IMAGE_TYPE_2D:
73                 case IMAGE_TYPE_BUFFER:
74                         // Not layered
75                         DE_ASSERT(layer == 0);
76                         return access;
77
78                 case IMAGE_TYPE_1D_ARRAY:
79                         return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
80
81                 case IMAGE_TYPE_2D_ARRAY:
82                 case IMAGE_TYPE_CUBE:
83                 case IMAGE_TYPE_CUBE_ARRAY:
84                 case IMAGE_TYPE_3D:                     // 3d texture is treated as if depth was the layers
85                         return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
86
87                 default:
88                         DE_FATAL("Internal test error");
89                         return tcu::ConstPixelBufferAccess();
90         }
91 }
92
93 //! \return true if all layers match in both pixel buffers
94 bool comparePixelBuffers (tcu::TestLog&                                         log,
95                                                   const Texture&                                        texture,
96                                                   const VkFormat                                        format,
97                                                   const tcu::ConstPixelBufferAccess     reference,
98                                                   const tcu::ConstPixelBufferAccess     result)
99 {
100         DE_ASSERT(reference.getFormat() == result.getFormat());
101         DE_ASSERT(reference.getSize() == result.getSize());
102
103         const bool intFormat = isIntegerFormat(format);
104         const bool is3d = (texture.type() == IMAGE_TYPE_3D);
105         const int numLayersOrSlices = (is3d ? texture.size().z() : texture.numLayers());
106         const int numCubeFaces = 6;
107
108         int passedLayers = 0;
109         for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
110         {
111                 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
112                 const std::string comparisonDesc = "Image Comparison, " +
113                         (isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
114                         is3d                     ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx));
115
116                 const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
117                 const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
118
119                 bool ok = false;
120                 if (intFormat)
121                         ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
122                 else
123                         ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
124
125                 if (ok)
126                         ++passedLayers;
127         }
128         return passedLayers == numLayersOrSlices;
129 }
130
131 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
132 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
133 {
134         DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
135
136         for (int z = 0; z < access.getDepth(); ++z)
137         for (int y = 0; y < access.getHeight(); ++y)
138         for (int x = 0; x < access.getWidth(); ++x)
139         {
140                 const tcu::Vec4 color(access.getPixel(x, y, z));
141                 tcu::Vec4 newColor = color;
142
143                 for (int i = 0; i < 4; ++i)
144                 {
145                         if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
146                         {
147                                 const tcu::Float16 f(color[i]);
148                                 if (f.isDenorm() || f.isInf() || f.isNaN())
149                                         newColor[i] = 0.0f;
150                         }
151                         else
152                         {
153                                 const tcu::Float32 f(color[i]);
154                                 if (f.isDenorm() || f.isInf() || f.isNaN())
155                                         newColor[i] = 0.0f;
156                         }
157                 }
158
159                 if (newColor != color)
160                         access.setPixel(newColor, x, y, z);
161         }
162 }
163
164 //!< replace invalid pixels in the image (-128)
165 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
166 {
167         DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
168
169         for (int z = 0; z < access.getDepth(); ++z)
170         for (int y = 0; y < access.getHeight(); ++y)
171         for (int x = 0; x < access.getWidth(); ++x)
172         {
173                 const tcu::IVec4 color(access.getPixelInt(x, y, z));
174                 tcu::IVec4 newColor = color;
175
176                 for (int i = 0; i < 4; ++i)
177                 {
178                         const deInt32 oldColor(color[i]);
179                         if (oldColor == -128) newColor[i] = -127;
180                 }
181
182                 if (newColor != color)
183                 access.setPixel(newColor, x, y, z);
184         }
185 }
186
187 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
188 {
189         // Generate a reference image data using the storage format
190
191         tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
192         const tcu::PixelBufferAccess access = reference.getAccess();
193
194         const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
195         const float storeColorBias = computeStoreColorBias(imageFormat);
196
197         const bool intFormat = isIntegerFormat(imageFormat);
198         const int xMax = imageSize.x() - 1;
199         const int yMax = imageSize.y() - 1;
200
201         for (int z = 0; z < imageSize.z(); ++z)
202         for (int y = 0; y < imageSize.y(); ++y)
203         for (int x = 0; x < imageSize.x(); ++x)
204         {
205                 const tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
206
207                 if (intFormat)
208                         access.setPixel(color, x, y, z);
209                 else
210                         access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
211         }
212
213         // If the image is to be accessed as a float texture, get rid of invalid values
214
215         if (isFloatFormat(readFormat) && imageFormat != readFormat)
216                 replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
217         if (isSnormFormat(readFormat) && imageFormat != readFormat)
218                 replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
219
220         return reference;
221 }
222
223 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
224 {
225         return generateReferenceImage(imageSize, imageFormat, imageFormat);
226 }
227
228 void flipHorizontally (const tcu::PixelBufferAccess access)
229 {
230         const int xMax = access.getWidth() - 1;
231         const int halfWidth = access.getWidth() / 2;
232
233         if (isIntegerFormat(mapTextureFormat(access.getFormat())))
234                 for (int z = 0; z < access.getDepth(); z++)
235                 for (int y = 0; y < access.getHeight(); y++)
236                 for (int x = 0; x < halfWidth; x++)
237                 {
238                         const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
239                         access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
240                         access.setPixel(temp, x, y, z);
241                 }
242         else
243                 for (int z = 0; z < access.getDepth(); z++)
244                 for (int y = 0; y < access.getHeight(); y++)
245                 for (int x = 0; x < halfWidth; x++)
246                 {
247                         const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
248                         access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
249                         access.setPixel(temp, x, y, z);
250                 }
251 }
252
253 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
254 {
255         return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
256 }
257
258 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
259 {
260         const DeviceInterface& vk = context.getDeviceInterface();
261
262         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
263         const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
264                 VK_ACCESS_SHADER_WRITE_BIT, 0u,
265                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
266                 image, fullImageSubresourceRange);
267
268         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);
269 }
270
271 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
272 {
273         const DeviceInterface& vk = context.getDeviceInterface();
274
275         const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
276                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
277                 buffer, 0ull, bufferSizeBytes);
278
279         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);
280 }
281
282 //! Copy all layers of an image to a buffer.
283 void commandCopyImageToBuffer (Context&                                 context,
284                                                            const VkCommandBuffer        cmdBuffer,
285                                                            const VkImage                        image,
286                                                            const VkBuffer                       buffer,
287                                                            const VkDeviceSize           bufferSizeBytes,
288                                                            const Texture&                       texture)
289 {
290         const DeviceInterface& vk = context.getDeviceInterface();
291
292         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
293         const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
294                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
295                 VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
296                 image, fullImageSubresourceRange);
297
298         const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
299
300         const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
301                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
302                 buffer, 0ull, bufferSizeBytes);
303
304         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);
305         vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &copyRegion);
306         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);
307 }
308
309 class StoreTest : public TestCase
310 {
311 public:
312         enum TestFlags
313         {
314                 FLAG_SINGLE_LAYER_BIND                          = 0x1,  //!< Run the shader multiple times, each time binding a different layer.
315                 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER     = 0x2,  //!< Declare the format of the images in the shader code
316         };
317
318                                                         StoreTest                       (tcu::TestContext&      testCtx,
319                                                                                                  const std::string&     name,
320                                                                                                  const std::string&     description,
321                                                                                                  const Texture&         texture,
322                                                                                                  const VkFormat         format,
323                                                                                                  const deUint32         flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
324
325         void                                    initPrograms            (SourceCollections& programCollection) const;
326
327         TestInstance*                   createInstance          (Context&                       context) const;
328
329 private:
330         const Texture                   m_texture;
331         const VkFormat                  m_format;
332         const bool                              m_declareImageFormatInShader;
333         const bool                              m_singleLayerBind;
334 };
335
336 StoreTest::StoreTest (tcu::TestContext&         testCtx,
337                                           const std::string&    name,
338                                           const std::string&    description,
339                                           const Texture&                texture,
340                                           const VkFormat                format,
341                                           const deUint32                flags)
342         : TestCase                                              (testCtx, name, description)
343         , m_texture                                             (texture)
344         , m_format                                              (format)
345         , m_declareImageFormatInShader  ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
346         , m_singleLayerBind                             ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
347 {
348         if (m_singleLayerBind)
349                 DE_ASSERT(m_texture.numLayers() > 1);
350 }
351
352 void StoreTest::initPrograms (SourceCollections& programCollection) const
353 {
354         const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
355         const float storeColorBias = computeStoreColorBias(m_format);
356         DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
357
358         const std::string xMax = de::toString(m_texture.size().x() - 1);
359         const std::string yMax = de::toString(m_texture.size().y() - 1);
360         const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
361         const std::string colorBaseExpr = signednessPrefix + "vec4("
362                 + "gx^gy^gz, "
363                 + "(" + xMax + "-gx)^gy^gz, "
364                 + "gx^(" + yMax + "-gy)^gz, "
365                 + "(" + xMax + "-gx)^(" + yMax + "-gy)^gz)";
366
367         const std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
368                                                                   + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
369
370         const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
371         const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
372
373         const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
374         const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
375         const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
376
377         for (deUint32 variant = 0; variant <= 1; variant++)
378         {
379                 std::ostringstream src;
380                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
381                         << "\n"
382                         << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
383                 if (variant == 0)
384                         src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
385                 else
386                         src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
387
388                 if (m_singleLayerBind)
389                         src << "layout (binding = 1) readonly uniform Constants {\n"
390                                 << "    int u_layerNdx;\n"
391                                 << "};\n";
392
393                 src << "\n"
394                         << "void main (void)\n"
395                         << "{\n"
396                         << "    int gx = int(gl_GlobalInvocationID.x);\n"
397                         << "    int gy = int(gl_GlobalInvocationID.y);\n"
398                         << "    int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
399                         << "    imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
400                         << "}\n";
401
402                 programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str());
403         }
404 }
405
406 //! Generic test iteration algorithm for image tests
407 class BaseTestInstance : public TestInstance
408 {
409 public:
410                                                                         BaseTestInstance                                                (Context&               context,
411                                                                                                                                                          const Texture& texture,
412                                                                                                                                                          const VkFormat format,
413                                                                                                                                                          const bool             declareImageFormatInShader,
414                                                                                                                                                          const bool             singleLayerBind);
415
416         tcu::TestStatus                 iterate                                                                 (void);
417
418         virtual                                                 ~BaseTestInstance                                               (void) {}
419
420 protected:
421         virtual VkDescriptorSetLayout   prepareDescriptors                                              (void) = 0;
422         virtual tcu::TestStatus                 verifyResult                                                    (void) = 0;
423
424         virtual void                                    commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer) = 0;
425         virtual void                                    commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer) = 0;
426         virtual void                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer) = 0;
427
428         virtual void                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
429                                                                                                                                                          const VkPipelineLayout pipelineLayout,
430                                                                                                                                                          const int                              layerNdx) = 0;
431         virtual void                                    checkRequirements                                               (void) {};
432
433         const Texture                                   m_texture;
434         const VkFormat                                  m_format;
435         const bool                                              m_declareImageFormatInShader;
436         const bool                                              m_singleLayerBind;
437 };
438
439 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind)
440         : TestInstance                                  (context)
441         , m_texture                                             (texture)
442         , m_format                                              (format)
443         , m_declareImageFormatInShader  (declareImageFormatInShader)
444         , m_singleLayerBind                             (singleLayerBind)
445 {
446 }
447
448 tcu::TestStatus BaseTestInstance::iterate (void)
449 {
450         checkRequirements();
451
452         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
453         const VkDevice                                  device                          = m_context.getDevice();
454         const VkQueue                                   queue                           = m_context.getUniversalQueue();
455         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
456
457         const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get(m_declareImageFormatInShader ? "comp" : "comp_fmt_unknown"), 0));
458
459         const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
460         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
461         const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
462
463         const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, queueFamilyIndex));
464         const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
465
466         beginCommandBuffer(vk, *cmdBuffer);
467
468         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
469         commandBeforeCompute(*cmdBuffer);
470
471         const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
472         const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
473         for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
474         {
475                 commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
476
477                 if (layerNdx > 0)
478                         commandBetweenShaderInvocations(*cmdBuffer);
479
480                 vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
481         }
482
483         commandAfterCompute(*cmdBuffer);
484
485         endCommandBuffer(vk, *cmdBuffer);
486
487         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
488
489         return verifyResult();
490 }
491
492 //! Base store test implementation
493 class StoreTestInstance : public BaseTestInstance
494 {
495 public:
496                                                                         StoreTestInstance                                               (Context&               context,
497                                                                                                                                                          const Texture& texture,
498                                                                                                                                                          const VkFormat format,
499                                                                                                                                                          const bool             declareImageFormatInShader,
500                                                                                                                                                          const bool             singleLayerBind);
501
502 protected:
503         tcu::TestStatus                                 verifyResult                                                    (void);
504
505         // Add empty implementations for functions that might be not needed
506         void                                                    commandBeforeCompute                                    (const VkCommandBuffer) {}
507         void                                                    commandBetweenShaderInvocations                 (const VkCommandBuffer) {}
508         void                                                    commandAfterCompute                                             (const VkCommandBuffer) {}
509         void                                                    checkRequirements                                               (void);
510
511         de::MovePtr<Buffer>                             m_imageBuffer;
512         const VkDeviceSize                              m_imageSizeBytes;
513 };
514
515 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind)
516         : BaseTestInstance              (context, texture, format, declareImageFormatInShader, singleLayerBind)
517         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
518 {
519         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
520         const VkDevice                  device          = m_context.getDevice();
521         Allocator&                              allocator       = m_context.getDefaultAllocator();
522
523         // A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
524
525         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
526                 vk, device, allocator,
527                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
528                 MemoryRequirement::HostVisible));
529 }
530
531 tcu::TestStatus StoreTestInstance::verifyResult (void)
532 {
533         const DeviceInterface&  vk              = m_context.getDeviceInterface();
534         const VkDevice                  device  = m_context.getDevice();
535
536         const tcu::IVec3 imageSize = m_texture.size();
537         const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
538
539         const Allocation& alloc = m_imageBuffer->getAllocation();
540         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
541         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, alloc.getHostPtr());
542
543         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
544                 return tcu::TestStatus::pass("Passed");
545         else
546                 return tcu::TestStatus::fail("Image comparison failed");
547 }
548
549 void StoreTestInstance::checkRequirements (void)
550 {
551         const VkPhysicalDeviceFeatures  features        = m_context.getDeviceFeatures();
552
553         if (!m_declareImageFormatInShader && !features.shaderStorageImageWriteWithoutFormat)
554                 throw tcu::NotSupportedError("shaderStorageImageWriteWithoutFormat feature not supported");
555 }
556
557 //! Store test for images
558 class ImageStoreTestInstance : public StoreTestInstance
559 {
560 public:
561                                                                                 ImageStoreTestInstance                                  (Context&                               context,
562                                                                                                                                                                  const Texture&                 texture,
563                                                                                                                                                                  const VkFormat                 format,
564                                                                                                                                                                  const bool                             declareImageFormatInShader,
565                                                                                                                                                                  const bool                             singleLayerBind);
566
567 protected:
568         VkDescriptorSetLayout                           prepareDescriptors                                              (void);
569         void                                                            commandBeforeCompute                                    (const VkCommandBuffer  cmdBuffer);
570         void                                                            commandBetweenShaderInvocations                 (const VkCommandBuffer  cmdBuffer);
571         void                                                            commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
572
573         void                                                            commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
574                                                                                                                                                                  const VkPipelineLayout pipelineLayout,
575                                                                                                                                                                  const int                              layerNdx);
576
577         de::MovePtr<Image>                                      m_image;
578         de::MovePtr<Buffer>                                     m_constantsBuffer;
579         const VkDeviceSize                                      m_constantsBufferChunkSizeBytes;
580         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
581         Move<VkDescriptorPool>                          m_descriptorPool;
582         std::vector<SharedVkDescriptorSet>      m_allDescriptorSets;
583         std::vector<SharedVkImageView>          m_allImageViews;
584 };
585
586 ImageStoreTestInstance::ImageStoreTestInstance (Context&                context,
587                                                                                                 const Texture&  texture,
588                                                                                                 const VkFormat  format,
589                                                                                                 const bool              declareImageFormatInShader,
590                                                                                                 const bool              singleLayerBind)
591         : StoreTestInstance                                     (context, texture, format, declareImageFormatInShader, singleLayerBind)
592         , m_constantsBufferChunkSizeBytes       (getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
593         , m_allDescriptorSets                           (texture.numLayers())
594         , m_allImageViews                                       (texture.numLayers())
595 {
596         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
597         const VkDevice                  device                          = m_context.getDevice();
598         Allocator&                              allocator                       = m_context.getDefaultAllocator();
599
600         m_image = de::MovePtr<Image>(new Image(
601                 vk, device, allocator,
602                 makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
603                 MemoryRequirement::Any));
604
605         // This buffer will be used to pass constants to the shader
606
607         const int numLayers = m_texture.numLayers();
608         const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
609         m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
610                 vk, device, allocator,
611                 makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
612                 MemoryRequirement::HostVisible));
613
614         {
615                 const Allocation& alloc = m_constantsBuffer->getAllocation();
616                 deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
617
618                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
619
620                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
621                 {
622                         deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
623                         *valuePtr = static_cast<deUint32>(layerNdx);
624                 }
625
626                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
627         }
628 }
629
630 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
631 {
632         const DeviceInterface&  vk              = m_context.getDeviceInterface();
633         const VkDevice                  device  = m_context.getDevice();
634
635         const int numLayers = m_texture.numLayers();
636         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
637                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
638                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
639                 .build(vk, device);
640
641         m_descriptorPool = DescriptorPoolBuilder()
642                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
643                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
644                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
645
646         if (m_singleLayerBind)
647         {
648                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
649                 {
650                         m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
651                         m_allImageViews[layerNdx]     = makeVkSharedPtr(makeImageView(
652                                                                                                 vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
653                                                                                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
654                 }
655         }
656         else // bind all layers at once
657         {
658                 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
659                 m_allImageViews[0] = makeVkSharedPtr(makeImageView(
660                                                                 vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
661                                                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
662         }
663
664         return *m_descriptorSetLayout;  // not passing the ownership
665 }
666
667 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
668 {
669         const DeviceInterface&  vk              = m_context.getDeviceInterface();
670         const VkDevice                  device  = m_context.getDevice();
671
672         const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
673         const VkImageView imageView = **m_allImageViews[layerNdx];
674
675         const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
676
677         // Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
678         const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
679                 m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
680
681         DescriptorSetUpdateBuilder()
682                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
683                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
684                 .update(vk, device);
685         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
686 }
687
688 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
689 {
690         const DeviceInterface& vk = m_context.getDeviceInterface();
691
692         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
693         const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
694                 0u, 0u,
695                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
696                 m_image->get(), fullImageSubresourceRange);
697
698         const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
699         const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
700                 VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
701                 m_constantsBuffer->get(), 0ull, constantsBufferSize);
702
703         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
704 }
705
706 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
707 {
708         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
709 }
710
711 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
712 {
713         commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
714 }
715
716 //! Store test for buffers
717 class BufferStoreTestInstance : public StoreTestInstance
718 {
719 public:
720                                                                         BufferStoreTestInstance                                 (Context&                               context,
721                                                                                                                                                          const Texture&                 texture,
722                                                                                                                                                          const VkFormat                 format,
723                                                                                                                                                          const bool                             declareImageFormatInShader);
724
725 protected:
726         VkDescriptorSetLayout                   prepareDescriptors                                              (void);
727         void                                                    commandAfterCompute                                             (const VkCommandBuffer  cmdBuffer);
728
729         void                                                    commandBindDescriptorsForLayer                  (const VkCommandBuffer  cmdBuffer,
730                                                                                                                                                          const VkPipelineLayout pipelineLayout,
731                                                                                                                                                          const int                              layerNdx);
732
733         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
734         Move<VkDescriptorPool>                  m_descriptorPool;
735         Move<VkDescriptorSet>                   m_descriptorSet;
736         Move<VkBufferView>                              m_bufferView;
737 };
738
739 BufferStoreTestInstance::BufferStoreTestInstance (Context&                      context,
740                                                                                                   const Texture&        texture,
741                                                                                                   const VkFormat        format,
742                                                                                                   const bool            declareImageFormatInShader)
743         : StoreTestInstance(context, texture, format, declareImageFormatInShader, false)
744 {
745 }
746
747 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
748 {
749         const DeviceInterface&  vk              = m_context.getDeviceInterface();
750         const VkDevice                  device  = m_context.getDevice();
751
752         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
753                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
754                 .build(vk, device);
755
756         m_descriptorPool = DescriptorPoolBuilder()
757                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
758                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
759
760         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
761         m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
762
763         return *m_descriptorSetLayout;  // not passing the ownership
764 }
765
766 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
767 {
768         DE_ASSERT(layerNdx == 0);
769         DE_UNREF(layerNdx);
770
771         const VkDevice                  device  = m_context.getDevice();
772         const DeviceInterface&  vk              = m_context.getDeviceInterface();
773
774         DescriptorSetUpdateBuilder()
775                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
776                 .update(vk, device);
777         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
778 }
779
780 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
781 {
782         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes);
783 }
784
785 class LoadStoreTest : public TestCase
786 {
787 public:
788         enum TestFlags
789         {
790                 FLAG_SINGLE_LAYER_BIND                          = 1 << 0,       //!< Run the shader multiple times, each time binding a different layer.
791                 FLAG_RESTRICT_IMAGES                            = 1 << 1,       //!< If given, images in the shader will be qualified with "restrict".
792                 FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER     = 1 << 2,       //!< Declare the format of the images in the shader code
793         };
794
795                                                         LoadStoreTest                   (tcu::TestContext&              testCtx,
796                                                                                                          const std::string&             name,
797                                                                                                          const std::string&             description,
798                                                                                                          const Texture&                 texture,
799                                                                                                          const VkFormat                 format,
800                                                                                                          const VkFormat                 imageFormat,
801                                                                                                          const deUint32                 flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
802
803         void                                    initPrograms                    (SourceCollections&             programCollection) const;
804         TestInstance*                   createInstance                  (Context&                               context) const;
805
806 private:
807         const Texture                   m_texture;
808         const VkFormat                  m_format;                                               //!< Format as accessed in the shader
809         const VkFormat                  m_imageFormat;                                  //!< Storage format
810         const bool                              m_declareImageFormatInShader;   //!< Whether the shader will specify the format layout qualifier of the images
811         const bool                              m_singleLayerBind;
812         const bool                              m_restrictImages;
813 };
814
815 LoadStoreTest::LoadStoreTest (tcu::TestContext&         testCtx,
816                                                           const std::string&    name,
817                                                           const std::string&    description,
818                                                           const Texture&                texture,
819                                                           const VkFormat                format,
820                                                           const VkFormat                imageFormat,
821                                                           const deUint32                flags)
822         : TestCase                                              (testCtx, name, description)
823         , m_texture                                             (texture)
824         , m_format                                              (format)
825         , m_imageFormat                                 (imageFormat)
826         , m_declareImageFormatInShader  ((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
827         , m_singleLayerBind                             ((flags & FLAG_SINGLE_LAYER_BIND) != 0)
828         , m_restrictImages                              ((flags & FLAG_RESTRICT_IMAGES) != 0)
829 {
830         if (m_singleLayerBind)
831                 DE_ASSERT(m_texture.numLayers() > 1);
832
833         DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
834 }
835
836 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
837 {
838         const int                       dimension                       = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
839         const ImageType         usedImageType           = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
840         const std::string       formatQualifierStr      = getShaderImageFormatQualifier(mapVkFormat(m_format));
841         const std::string       imageTypeStr            = getShaderImageType(mapVkFormat(m_format), usedImageType);
842         const std::string       maybeRestrictStr        = (m_restrictImages ? "restrict " : "");
843         const std::string       xMax                            = de::toString(m_texture.size().x() - 1);
844
845         for (deUint32 variant = 0; variant <= 1; variant++)
846         {
847                 std::ostringstream src;
848                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
849                         << "\n";
850                 if (variant != 0)
851                 {
852                         src << "#extension GL_EXT_shader_image_load_formatted : require\n";
853                 }
854                 src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
855                 if (variant == 0)
856                         src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
857                 else
858                         src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
859                 src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n"
860                         << "\n"
861                         << "void main (void)\n"
862                         << "{\n"
863                         << (dimension == 1 ?
864                                 "    int pos = int(gl_GlobalInvocationID.x);\n"
865                                 "    imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n"
866                                 : dimension == 2 ?
867                                 "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
868                                 "    imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n"
869                                 : dimension == 3 ?
870                                 "    ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
871                                 "    imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n"
872                                 : "")
873                         << "}\n";
874
875                 programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str());
876         }
877 }
878
879 //! Load/store test base implementation
880 class LoadStoreTestInstance : public BaseTestInstance
881 {
882 public:
883                                                                         LoadStoreTestInstance                           (Context&                       context,
884                                                                                                                                                  const Texture&         texture,
885                                                                                                                                                  const VkFormat         format,
886                                                                                                                                                  const VkFormat         imageFormat,
887                                                                                                                                                  const bool                     declareImageFormatInShader,
888                                                                                                                                                  const bool                     singleLayerBind);
889
890 protected:
891         virtual Buffer*                                 getResultBuffer                                         (void) const = 0;       //!< Get the buffer that contains the result image
892
893         tcu::TestStatus                                 verifyResult                                            (void);
894
895         // Add empty implementations for functions that might be not needed
896         void                                                    commandBeforeCompute                            (const VkCommandBuffer) {}
897         void                                                    commandBetweenShaderInvocations         (const VkCommandBuffer) {}
898         void                                                    commandAfterCompute                                     (const VkCommandBuffer) {}
899         void                                                    checkRequirements                                       (void);
900
901         de::MovePtr<Buffer>                             m_imageBuffer;          //!< Source data and helper buffer
902         const VkDeviceSize                              m_imageSizeBytes;
903         const VkFormat                                  m_imageFormat;          //!< Image format (for storage, may be different than texture format)
904         tcu::TextureLevel                               m_referenceImage;       //!< Used as input data and later to verify result image
905 };
906
907 LoadStoreTestInstance::LoadStoreTestInstance (Context&                  context,
908                                                                                           const Texture&        texture,
909                                                                                           const VkFormat        format,
910                                                                                           const VkFormat        imageFormat,
911                                                                                           const bool            declareImageFormatInShader,
912                                                                                           const bool            singleLayerBind)
913         : BaseTestInstance              (context, texture, format, declareImageFormatInShader, singleLayerBind)
914         , m_imageSizeBytes              (getImageSizeBytes(texture.size(), format))
915         , m_imageFormat                 (imageFormat)
916         , m_referenceImage              (generateReferenceImage(texture.size(), imageFormat, format))
917 {
918         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
919         const VkDevice                  device          = m_context.getDevice();
920         Allocator&                              allocator       = m_context.getDefaultAllocator();
921
922         // A helper buffer with enough space to hold the whole image.
923
924         m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
925                 vk, device, allocator,
926                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
927                 MemoryRequirement::HostVisible));
928
929         // Copy reference data to buffer for subsequent upload to image.
930
931         const Allocation& alloc = m_imageBuffer->getAllocation();
932         deMemcpy(alloc.getHostPtr(), m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
933         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
934 }
935
936 tcu::TestStatus LoadStoreTestInstance::verifyResult     (void)
937 {
938         const DeviceInterface&  vk              = m_context.getDeviceInterface();
939         const VkDevice                  device  = m_context.getDevice();
940
941         // Apply the same transformation as done in the shader
942         const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
943         flipHorizontally(reference);
944
945         const Allocation& alloc = getResultBuffer()->getAllocation();
946         invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
947         const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), alloc.getHostPtr());
948
949         if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
950                 return tcu::TestStatus::pass("Passed");
951         else
952                 return tcu::TestStatus::fail("Image comparison failed");
953 }
954
955 void LoadStoreTestInstance::checkRequirements (void)
956 {
957         const VkPhysicalDeviceFeatures  features        = m_context.getDeviceFeatures();
958
959         if (!m_declareImageFormatInShader && !features.shaderStorageImageReadWithoutFormat)
960                 throw tcu::NotSupportedError("shaderStorageImageReadWithoutFormat feature not supported");
961 }
962
963
964 //! Load/store test for images
965 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
966 {
967 public:
968                                                                                 ImageLoadStoreTestInstance                      (Context&                               context,
969                                                                                                                                                          const Texture&                 texture,
970                                                                                                                                                          const VkFormat                 format,
971                                                                                                                                                          const VkFormat                 imageFormat,
972                                                                                                                                                          const bool                             declareImageFormatInShader,
973                                                                                                                                                          const bool                             singleLayerBind);
974
975 protected:
976         VkDescriptorSetLayout                           prepareDescriptors                                      (void);
977         void                                                            commandBeforeCompute                            (const VkCommandBuffer  cmdBuffer);
978         void                                                            commandBetweenShaderInvocations         (const VkCommandBuffer  cmdBuffer);
979         void                                                            commandAfterCompute                                     (const VkCommandBuffer  cmdBuffer);
980
981         void                                                            commandBindDescriptorsForLayer          (const VkCommandBuffer  cmdBuffer,
982                                                                                                                                                          const VkPipelineLayout pipelineLayout,
983                                                                                                                                                          const int                              layerNdx);
984
985         Buffer*                                                         getResultBuffer                                         (void) const { return m_imageBuffer.get(); }
986
987         de::MovePtr<Image>                                      m_imageSrc;
988         de::MovePtr<Image>                                      m_imageDst;
989         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
990         Move<VkDescriptorPool>                          m_descriptorPool;
991         std::vector<SharedVkDescriptorSet>      m_allDescriptorSets;
992         std::vector<SharedVkImageView>          m_allSrcImageViews;
993         std::vector<SharedVkImageView>          m_allDstImageViews;
994 };
995
996 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context&                context,
997                                                                                                                 const Texture&  texture,
998                                                                                                                 const VkFormat  format,
999                                                                                                                 const VkFormat  imageFormat,
1000                                                                                                                 const bool              declareImageFormatInShader,
1001                                                                                                                 const bool              singleLayerBind)
1002         : LoadStoreTestInstance (context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind)
1003         , m_allDescriptorSets   (texture.numLayers())
1004         , m_allSrcImageViews    (texture.numLayers())
1005         , m_allDstImageViews    (texture.numLayers())
1006 {
1007         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
1008         const VkDevice                          device                          = m_context.getDevice();
1009         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
1010         const VkImageCreateFlags        imageFlags                      = (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1011
1012         m_imageSrc = de::MovePtr<Image>(new Image(
1013                 vk, device, allocator,
1014                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
1015                 MemoryRequirement::Any));
1016
1017         m_imageDst = de::MovePtr<Image>(new Image(
1018                 vk, device, allocator,
1019                 makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
1020                 MemoryRequirement::Any));
1021 }
1022
1023 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1024 {
1025         const VkDevice                  device  = m_context.getDevice();
1026         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1027
1028         const int numLayers = m_texture.numLayers();
1029         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1030                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1031                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1032                 .build(vk, device);
1033
1034         m_descriptorPool = DescriptorPoolBuilder()
1035                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1036                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1037                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1038
1039         if (m_singleLayerBind)
1040         {
1041                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1042                 {
1043                         const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1044                         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1045
1046                         m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1047                         m_allSrcImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1048                         m_allDstImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1049                 }
1050         }
1051         else // bind all layers at once
1052         {
1053                 const VkImageViewType viewType = mapImageViewType(m_texture.type());
1054                 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1055
1056                 m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1057                 m_allSrcImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1058                 m_allDstImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1059         }
1060
1061         return *m_descriptorSetLayout;  // not passing the ownership
1062 }
1063
1064 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1065 {
1066         const VkDevice                  device  = m_context.getDevice();
1067         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1068
1069         const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1070         const VkImageView         srcImageView  = **m_allSrcImageViews[layerNdx];
1071         const VkImageView         dstImageView  = **m_allDstImageViews[layerNdx];
1072
1073         const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1074         const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1075
1076         DescriptorSetUpdateBuilder()
1077                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1078                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1079                 .update(vk, device);
1080         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1081 }
1082
1083 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1084 {
1085         const DeviceInterface& vk = m_context.getDeviceInterface();
1086
1087         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1088         {
1089                 const VkImageMemoryBarrier preCopyImageBarriers[] =
1090                 {
1091                         makeImageMemoryBarrier(
1092                                 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1093                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1094                                 m_imageSrc->get(), fullImageSubresourceRange),
1095                         makeImageMemoryBarrier(
1096                                 0u, VK_ACCESS_SHADER_WRITE_BIT,
1097                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1098                                 m_imageDst->get(), fullImageSubresourceRange)
1099                 };
1100
1101                 const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1102                         VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1103                         m_imageBuffer->get(), 0ull, m_imageSizeBytes);
1104
1105                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1106                         (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1107         }
1108         {
1109                 const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1110                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1111                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1112                         m_imageSrc->get(), fullImageSubresourceRange);
1113
1114                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1115
1116                 vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1117                 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);
1118         }
1119 }
1120
1121 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1122 {
1123         commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1124 }
1125
1126 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1127 {
1128         commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1129 }
1130
1131 //! Load/store test for buffers
1132 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
1133 {
1134 public:
1135                                                                         BufferLoadStoreTestInstance             (Context&                               context,
1136                                                                                                                                          const Texture&                 texture,
1137                                                                                                                                          const VkFormat                 format,
1138                                                                                                                                          const VkFormat                 imageFormat,
1139                                                                                                                                          const bool                             declareImageFormatInShader);
1140
1141 protected:
1142         VkDescriptorSetLayout                   prepareDescriptors                              (void);
1143         void                                                    commandAfterCompute                             (const VkCommandBuffer  cmdBuffer);
1144
1145         void                                                    commandBindDescriptorsForLayer  (const VkCommandBuffer  cmdBuffer,
1146                                                                                                                                          const VkPipelineLayout pipelineLayout,
1147                                                                                                                                          const int                              layerNdx);
1148
1149         Buffer*                                                 getResultBuffer                                 (void) const { return m_imageBufferDst.get(); }
1150
1151         de::MovePtr<Buffer>                             m_imageBufferDst;
1152         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
1153         Move<VkDescriptorPool>                  m_descriptorPool;
1154         Move<VkDescriptorSet>                   m_descriptorSet;
1155         Move<VkBufferView>                              m_bufferViewSrc;
1156         Move<VkBufferView>                              m_bufferViewDst;
1157 };
1158
1159 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context&                      context,
1160                                                                                                                   const Texture&        texture,
1161                                                                                                                   const VkFormat        format,
1162                                                                                                                   const VkFormat        imageFormat,
1163                                                                                                                   const bool            declareImageFormatInShader)
1164         : LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false)
1165 {
1166         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1167         const VkDevice                  device          = m_context.getDevice();
1168         Allocator&                              allocator       = m_context.getDefaultAllocator();
1169
1170         // Create a destination buffer.
1171
1172         m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
1173                 vk, device, allocator,
1174                 makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
1175                 MemoryRequirement::HostVisible));
1176 }
1177
1178 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
1179 {
1180         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1181         const VkDevice                  device  = m_context.getDevice();
1182
1183         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1184                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1185                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1186                 .build(vk, device);
1187
1188         m_descriptorPool = DescriptorPoolBuilder()
1189                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1190                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1191                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1192
1193         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1194         m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
1195         m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), m_format, 0ull, m_imageSizeBytes);
1196
1197         return *m_descriptorSetLayout;  // not passing the ownership
1198 }
1199
1200 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1201 {
1202         DE_ASSERT(layerNdx == 0);
1203         DE_UNREF(layerNdx);
1204
1205         const VkDevice                  device  = m_context.getDevice();
1206         const DeviceInterface&  vk              = m_context.getDeviceInterface();
1207
1208         DescriptorSetUpdateBuilder()
1209                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewSrc.get())
1210                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
1211                 .update(vk, device);
1212         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1213 }
1214
1215 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1216 {
1217         commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes);
1218 }
1219
1220 TestInstance* StoreTest::createInstance (Context& context) const
1221 {
1222         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1223                 return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader);
1224         else
1225                 return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind);
1226 }
1227
1228 TestInstance* LoadStoreTest::createInstance (Context& context) const
1229 {
1230         if (m_texture.type() == IMAGE_TYPE_BUFFER)
1231                 return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader);
1232         else
1233                 return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind);
1234 }
1235
1236 static const Texture s_textures[] =
1237 {
1238         Texture(IMAGE_TYPE_1D,                  tcu::IVec3(64,  1,      1),     1),
1239         Texture(IMAGE_TYPE_1D_ARRAY,    tcu::IVec3(64,  1,      1),     8),
1240         Texture(IMAGE_TYPE_2D,                  tcu::IVec3(64,  64,     1),     1),
1241         Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(64,  64,     1),     8),
1242         Texture(IMAGE_TYPE_3D,                  tcu::IVec3(64,  64,     8),     1),
1243         Texture(IMAGE_TYPE_CUBE,                tcu::IVec3(64,  64,     1),     6),
1244         Texture(IMAGE_TYPE_CUBE_ARRAY,  tcu::IVec3(64,  64,     1),     2*6),
1245         Texture(IMAGE_TYPE_BUFFER,              tcu::IVec3(64,  1,      1),     1),
1246 };
1247
1248 const Texture& getTestTexture (const ImageType imageType)
1249 {
1250         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1251                 if (s_textures[textureNdx].type() == imageType)
1252                         return s_textures[textureNdx];
1253
1254         DE_FATAL("Internal error");
1255         return s_textures[0];
1256 }
1257
1258 static const VkFormat s_formats[] =
1259 {
1260         VK_FORMAT_R32G32B32A32_SFLOAT,
1261         VK_FORMAT_R16G16B16A16_SFLOAT,
1262         VK_FORMAT_R32_SFLOAT,
1263
1264         VK_FORMAT_R32G32B32A32_UINT,
1265         VK_FORMAT_R16G16B16A16_UINT,
1266         VK_FORMAT_R8G8B8A8_UINT,
1267         VK_FORMAT_R32_UINT,
1268
1269         VK_FORMAT_R32G32B32A32_SINT,
1270         VK_FORMAT_R16G16B16A16_SINT,
1271         VK_FORMAT_R8G8B8A8_SINT,
1272         VK_FORMAT_R32_SINT,
1273
1274         VK_FORMAT_R8G8B8A8_UNORM,
1275
1276         VK_FORMAT_R8G8B8A8_SNORM,
1277 };
1278
1279 } // anonymous ns
1280
1281 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
1282 {
1283         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
1284         de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
1285         de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
1286
1287         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1288         {
1289                 const Texture& texture = s_textures[textureNdx];
1290                 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1291                 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1292                 const bool isLayered = (texture.numLayers() > 1);
1293
1294                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1295                 {
1296                         groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
1297                         groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
1298
1299                         if (isLayered)
1300                                 groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
1301                                                                                                                 texture, s_formats[formatNdx],
1302                                                                                                                 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
1303                 }
1304
1305                 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
1306                 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
1307         }
1308
1309         testGroup->addChild(testGroupWithFormat.release());
1310         testGroup->addChild(testGroupWithoutFormat.release());
1311
1312         return testGroup.release();
1313 }
1314
1315 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
1316 {
1317         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
1318         de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
1319         de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
1320
1321         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1322         {
1323                 const Texture& texture = s_textures[textureNdx];
1324                 de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1325                 de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1326                 const bool isLayered = (texture.numLayers() > 1);
1327
1328                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1329                 {
1330                         groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
1331                         groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
1332
1333                         if (isLayered)
1334                                 groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
1335                                                                                                                 texture, s_formats[formatNdx], s_formats[formatNdx],
1336                                                                                                                 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
1337                 }
1338
1339                 testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
1340                 testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
1341         }
1342
1343         testGroup->addChild(testGroupWithFormat.release());
1344         testGroup->addChild(testGroupWithoutFormat.release());
1345
1346         return testGroup.release();
1347 }
1348
1349 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
1350 {
1351         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret", "Cases with differing texture and image formats"));
1352
1353         for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
1354         {
1355                 const Texture& texture = s_textures[textureNdx];
1356                 de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
1357
1358                 for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
1359                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
1360                 {
1361                         const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
1362                         if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
1363                                 groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
1364                 }
1365                 testGroup->addChild(groupByImageViewType.release());
1366         }
1367
1368         return testGroup.release();
1369 }
1370
1371 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
1372 {
1373         const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
1374         const Texture& texture = getTestTexture(imageType);
1375         return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES));
1376 }
1377
1378 } // image
1379 } // vkt