Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineImageUtil.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
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 Utilities for images.
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineImageUtil.hpp"
26 #include "vkImageUtil.hpp"
27 #include "vkMemUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuAstcUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deSharedPtr.hpp"
36
37 namespace vkt
38 {
39 namespace pipeline
40 {
41
42 using namespace vk;
43
44 /*! Gets the next multiple of a given divisor */
45 static deUint32 getNextMultiple (deUint32 divisor, deUint32 value)
46 {
47         if (value % divisor == 0)
48         {
49                 return value;
50         }
51         return value + divisor - (value % divisor);
52 }
53
54 /*! Gets the next value that is multiple of all given divisors */
55 static deUint32 getNextMultiple (const std::vector<deUint32>& divisors, deUint32 value)
56 {
57         deUint32        nextMultiple            = value;
58         bool            nextMultipleFound       = false;
59
60         while (true)
61         {
62                 nextMultipleFound = true;
63
64                 for (size_t divNdx = 0; divNdx < divisors.size(); divNdx++)
65                         nextMultipleFound = nextMultipleFound && (nextMultiple % divisors[divNdx] == 0);
66
67                 if (nextMultipleFound)
68                         break;
69
70                 DE_ASSERT(nextMultiple < ~((deUint32)0u));
71                 nextMultiple = getNextMultiple(divisors[0], nextMultiple + 1);
72         }
73
74         return nextMultiple;
75 }
76
77 bool isSupportedSamplableFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
78 {
79         if (isCompressedFormat(format))
80         {
81                 VkPhysicalDeviceFeatures                physicalFeatures;
82                 const tcu::CompressedTexFormat  compressedFormat        = mapVkCompressedFormat(format);
83
84                 instanceInterface.getPhysicalDeviceFeatures(device, &physicalFeatures);
85
86                 if (tcu::isAstcFormat(compressedFormat))
87                 {
88                         if (!physicalFeatures.textureCompressionASTC_LDR)
89                                 return false;
90                 }
91                 else if (tcu::isEtcFormat(compressedFormat))
92                 {
93                         if (!physicalFeatures.textureCompressionETC2)
94                                 return false;
95                 }
96                 else
97                 {
98                         DE_FATAL("Unsupported compressed format");
99                 }
100         }
101
102         VkFormatProperties      formatProps;
103         instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
104
105         return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u;
106 }
107
108 bool isLinearFilteringSupported (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling tiling)
109 {
110         const VkFormatProperties        formatProperties        = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
111         const VkFormatFeatureFlags      formatFeatures          = tiling == VK_IMAGE_TILING_LINEAR
112                                                                                                         ? formatProperties.linearTilingFeatures
113                                                                                                         : formatProperties.optimalTilingFeatures;
114
115         return (formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) != 0;
116 }
117
118 bool isMinMaxFilteringSupported (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling tiling)
119 {
120         const VkFormatProperties        formatProperties        = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
121         const VkFormatFeatureFlags      formatFeatures          = tiling == VK_IMAGE_TILING_LINEAR
122                                                                                                         ? formatProperties.linearTilingFeatures
123                                                                                                         : formatProperties.optimalTilingFeatures;
124
125         return (formatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT) != 0;
126 }
127
128 static bool isBorderColorInt (VkFormat format, bool useStencilAspect)
129 {
130         return (!isCompressedFormat(format) && (isIntFormat(format) || isUintFormat(format) || (isDepthStencilFormat(format) && useStencilAspect)));
131 }
132
133 VkBorderColor getFormatBorderColor (BorderColor color, VkFormat format, bool useStencilAspect)
134 {
135         if (isBorderColorInt(format, useStencilAspect))
136         {
137                 switch (color)
138                 {
139                         case BORDER_COLOR_OPAQUE_BLACK:                 return VK_BORDER_COLOR_INT_OPAQUE_BLACK;
140                         case BORDER_COLOR_OPAQUE_WHITE:                 return VK_BORDER_COLOR_INT_OPAQUE_WHITE;
141                         case BORDER_COLOR_TRANSPARENT_BLACK:    return VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
142                         case BORDER_COLOR_CUSTOM:                               return VK_BORDER_COLOR_INT_CUSTOM_EXT;
143                         default:
144                                 break;
145                 }
146         }
147         else
148         {
149                 switch (color)
150                 {
151                         case BORDER_COLOR_OPAQUE_BLACK:                 return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
152                         case BORDER_COLOR_OPAQUE_WHITE:                 return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
153                         case BORDER_COLOR_TRANSPARENT_BLACK:    return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
154                         case BORDER_COLOR_CUSTOM:                               return VK_BORDER_COLOR_FLOAT_CUSTOM_EXT;
155                         default:
156                                 break;
157                 }
158         }
159
160         DE_ASSERT(false);
161         return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
162 }
163
164 rr::GenericVec4 getFormatCustomBorderColor      (tcu::Vec4 floatValue, tcu::IVec4 intValue, vk::VkFormat format, bool useStencilAspect)
165 {
166         if (isBorderColorInt(format, useStencilAspect))
167         {
168                 return rr::GenericVec4(intValue);
169         }
170         else
171         {
172                 return rr::GenericVec4(floatValue);
173         }
174 }
175
176 void getLookupScaleBias (vk::VkFormat format, tcu::Vec4& lookupScale, tcu::Vec4& lookupBias, bool useStencilAspect)
177 {
178         if (!isCompressedFormat(format))
179         {
180                 const auto tcuFormat = mapVkFormat(format);
181
182                 if (useStencilAspect)
183                 {
184                         DE_ASSERT(tcu::hasStencilComponent(tcuFormat.order));
185                         lookupScale = tcu::Vec4(1.0f / 255.0f, 1.0f, 1.0f, 1.0f);
186                         lookupBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
187                 }
188                 else
189                 {
190                         const tcu::TextureFormatInfo    fmtInfo = tcu::getTextureFormatInfo(tcuFormat);
191
192                         // Needed to normalize various formats to 0..1 range for writing into RT
193                         lookupScale     = fmtInfo.lookupScale;
194                         lookupBias      = fmtInfo.lookupBias;
195                 }
196         }
197         else
198         {
199                 switch (format)
200                 {
201                         case VK_FORMAT_EAC_R11_SNORM_BLOCK:
202                                 lookupScale     = tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f);
203                                 lookupBias      = tcu::Vec4(0.5f, 0.0f, 0.0f, 0.0f);
204                                 break;
205
206                         case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
207                                 lookupScale     = tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f);
208                                 lookupBias      = tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f);
209                                 break;
210
211                         default:
212                                 // else: All supported compressed formats are fine with no normalization.
213                                 //               ASTC LDR blocks decompress to f16 so querying normalization parameters
214                                 //               based on uncompressed formats would actually lead to massive precision loss
215                                 //               and complete lack of coverage in case of R8G8B8A8_UNORM RT.
216                                 lookupScale     = tcu::Vec4(1.0f);
217                                 lookupBias      = tcu::Vec4(0.0f);
218                                 break;
219                 }
220         }
221 }
222
223 de::MovePtr<tcu::TextureLevel> readColorAttachment (const vk::DeviceInterface&  vk,
224                                                                                                         vk::VkDevice                            device,
225                                                                                                         vk::VkQueue                                     queue,
226                                                                                                         deUint32                                        queueFamilyIndex,
227                                                                                                         vk::Allocator&                          allocator,
228                                                                                                         vk::VkImage                                     image,
229                                                                                                         vk::VkFormat                            format,
230                                                                                                         const tcu::UVec2&                       renderSize,
231                                                                                                         vk::VkImageLayout                       oldLayout)
232 {
233         Move<VkBuffer>                                  buffer;
234         de::MovePtr<Allocation>                 bufferAlloc;
235         Move<VkCommandPool>                             cmdPool;
236         Move<VkCommandBuffer>                   cmdBuffer;
237         Move<VkFence>                                   fence;
238         const tcu::TextureFormat                tcuFormat               = mapVkFormat(format);
239         const VkDeviceSize                              pixelDataSize   = renderSize.x() * renderSize.y() * tcuFormat.getPixelSize();
240         de::MovePtr<tcu::TextureLevel>  resultLevel             (new tcu::TextureLevel(tcuFormat, renderSize.x(), renderSize.y()));
241
242         // Create destination buffer
243         {
244                 const VkBufferCreateInfo bufferParams =
245                 {
246                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
247                         DE_NULL,                                                                        // const void*                  pNext;
248                         0u,                                                                                     // VkBufferCreateFlags  flags;
249                         pixelDataSize,                                                          // VkDeviceSize                 size;
250                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
251                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
252                         0u,                                                                                     // deUint32                             queueFamilyIndexCount;
253                         DE_NULL                                                                         // const deUint32*              pQueueFamilyIndices;
254                 };
255
256                 buffer          = createBuffer(vk, device, &bufferParams);
257                 bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
258                 VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
259         }
260
261         // Create command pool and buffer
262         cmdPool         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
263         cmdBuffer       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
264
265         // Create fence
266         fence = createFence(vk, device);
267
268         beginCommandBuffer(vk, *cmdBuffer);
269         copyImageToBuffer(vk, *cmdBuffer, image, *buffer, tcu::IVec2(renderSize.x(), renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, oldLayout);
270         endCommandBuffer(vk, *cmdBuffer);
271
272         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
273
274         // Read buffer data
275         invalidateAlloc(vk, device, *bufferAlloc);
276         tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));
277
278         return resultLevel;
279 }
280
281 de::MovePtr<tcu::TextureLevel> readDepthAttachment (const vk::DeviceInterface&  vk,
282                                                                                                         vk::VkDevice                            device,
283                                                                                                         vk::VkQueue                                     queue,
284                                                                                                         deUint32                                        queueFamilyIndex,
285                                                                                                         vk::Allocator&                          allocator,
286                                                                                                         vk::VkImage                                     image,
287                                                                                                         vk::VkFormat                            format,
288                                                                                                         const tcu::UVec2&                       renderSize,
289                                                                                                         vk::VkImageLayout                       currentLayout)
290 {
291         Move<VkBuffer>                                  buffer;
292         de::MovePtr<Allocation>                 bufferAlloc;
293         Move<VkCommandPool>                             cmdPool;
294         Move<VkCommandBuffer>                   cmdBuffer;
295
296         tcu::TextureFormat                              retFormat               (tcu::TextureFormat::D, tcu::TextureFormat::CHANNELTYPE_LAST);
297         tcu::TextureFormat                              bufferFormat    (tcu::TextureFormat::D, tcu::TextureFormat::CHANNELTYPE_LAST);
298         const VkImageAspectFlags                barrierAspect   = VK_IMAGE_ASPECT_DEPTH_BIT | (mapVkFormat(format).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0);
299
300         switch (format)
301         {
302         case vk::VK_FORMAT_D16_UNORM:
303         case vk::VK_FORMAT_D16_UNORM_S8_UINT:
304                 bufferFormat.type = retFormat.type = tcu::TextureFormat::UNORM_INT16;
305                 break;
306         case vk::VK_FORMAT_D24_UNORM_S8_UINT:
307         case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
308                 retFormat.type = tcu::TextureFormat::UNORM_INT24;
309                 // vkCmdCopyBufferToImage copies D24 data to 32-bit pixels.
310                 bufferFormat.type = tcu::TextureFormat::UNSIGNED_INT_24_8_REV;
311                 break;
312         case vk::VK_FORMAT_D32_SFLOAT:
313         case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
314                 bufferFormat.type = retFormat.type = tcu::TextureFormat::FLOAT;
315                 break;
316         default:
317                 TCU_FAIL("unrecognized format");
318         }
319
320         const VkDeviceSize                              pixelDataSize   = renderSize.x() * renderSize.y() * bufferFormat.getPixelSize();
321         de::MovePtr<tcu::TextureLevel>  resultLevel             (new tcu::TextureLevel(retFormat, renderSize.x(), renderSize.y()));
322
323         // Create destination buffer
324         {
325                 const VkBufferCreateInfo bufferParams =
326                 {
327                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
328                         DE_NULL,                                                                        // const void*                  pNext;
329                         0u,                                                                                     // VkBufferCreateFlags  flags;
330                         pixelDataSize,                                                          // VkDeviceSize                 size;
331                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
332                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
333                         0u,                                                                                     // deUint32                             queueFamilyIndexCount;
334                         DE_NULL                                                                         // const deUint32*              pQueueFamilyIndices;
335                 };
336
337                 buffer          = createBuffer(vk, device, &bufferParams);
338                 bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
339                 VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
340         }
341
342         // Create command pool and buffer
343         cmdPool         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
344         cmdBuffer       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
345
346         beginCommandBuffer(vk, *cmdBuffer);
347         copyImageToBuffer(vk, *cmdBuffer, image, *buffer, tcu::IVec2(renderSize.x(), renderSize.y()), VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, currentLayout, 1u, barrierAspect, VK_IMAGE_ASPECT_DEPTH_BIT);
348         endCommandBuffer(vk, *cmdBuffer);
349
350         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
351
352         // Read buffer data
353         invalidateAlloc(vk, device, *bufferAlloc);
354         tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(bufferFormat, resultLevel->getSize(), bufferAlloc->getHostPtr()));
355
356         return resultLevel;
357 }
358
359 de::MovePtr<tcu::TextureLevel> readStencilAttachment (const vk::DeviceInterface&        vk,
360                                                                                                           vk::VkDevice                                  device,
361                                                                                                           vk::VkQueue                                   queue,
362                                                                                                           deUint32                                              queueFamilyIndex,
363                                                                                                           vk::Allocator&                                allocator,
364                                                                                                           vk::VkImage                                   image,
365                                                                                                           vk::VkFormat                                  format,
366                                                                                                           const tcu::UVec2&                             renderSize,
367                                                                                                           vk::VkImageLayout                             currentLayout)
368 {
369         Move<VkBuffer>                                  buffer;
370         de::MovePtr<Allocation>                 bufferAlloc;
371         Move<VkCommandPool>                             cmdPool;
372         Move<VkCommandBuffer>                   cmdBuffer;
373
374         tcu::TextureFormat                              retFormat               (tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
375         tcu::TextureFormat                              bufferFormat    (tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
376
377         const VkImageAspectFlags                barrierAspect   = VK_IMAGE_ASPECT_STENCIL_BIT | (mapVkFormat(format).order == tcu::TextureFormat::DS ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0);
378         const VkDeviceSize                              pixelDataSize   = renderSize.x() * renderSize.y() * bufferFormat.getPixelSize();
379         de::MovePtr<tcu::TextureLevel>  resultLevel             (new tcu::TextureLevel(retFormat, renderSize.x(), renderSize.y()));
380
381         // Create destination buffer
382         {
383                 const VkBufferCreateInfo bufferParams =
384                 {
385                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
386                         DE_NULL,                                                                        // const void*                  pNext;
387                         0u,                                                                                     // VkBufferCreateFlags  flags;
388                         pixelDataSize,                                                          // VkDeviceSize                 size;
389                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
390                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
391                         0u,                                                                                     // deUint32                             queueFamilyIndexCount;
392                         DE_NULL                                                                         // const deUint32*              pQueueFamilyIndices;
393                 };
394
395                 buffer          = createBuffer(vk, device, &bufferParams);
396                 bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
397                 VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
398         }
399
400         // Create command pool and buffer
401         cmdPool         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
402         cmdBuffer       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
403
404         beginCommandBuffer(vk, *cmdBuffer);
405         copyImageToBuffer(vk, *cmdBuffer, image, *buffer, tcu::IVec2(renderSize.x(), renderSize.y()), VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, currentLayout, 1u, barrierAspect, VK_IMAGE_ASPECT_STENCIL_BIT);
406         endCommandBuffer(vk, *cmdBuffer);
407
408         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
409
410         // Read buffer data
411         invalidateAlloc(vk, device, *bufferAlloc);
412         tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(bufferFormat, resultLevel->getSize(), bufferAlloc->getHostPtr()));
413
414         return resultLevel;
415 }
416
417 void uploadTestTextureInternal (const DeviceInterface&  vk,
418                                                                 VkDevice                                device,
419                                                                 VkQueue                                 queue,
420                                                                 deUint32                                queueFamilyIndex,
421                                                                 Allocator&                              allocator,
422                                                                 const TestTexture&              srcTexture,
423                                                                 const TestTexture*              srcStencilTexture,
424                                                                 tcu::TextureFormat              format,
425                                                                 VkImage                                 destImage,
426                                                                 VkImageLayout                   destImageLayout)
427 {
428         Move<VkBuffer>                                  buffer;
429         de::MovePtr<Allocation>                 bufferAlloc;
430         Move<VkCommandPool>                             cmdPool;
431         Move<VkCommandBuffer>                   cmdBuffer;
432         const VkImageAspectFlags                imageAspectFlags        = getImageAspectFlags(format);
433         deUint32                                                stencilOffset           = 0u;
434         std::vector<VkBufferImageCopy>  copyRegions                     = srcTexture.getBufferCopyRegions();
435         deUint32                                                bufferSize                      = (srcTexture.isCompressed())? srcTexture.getCompressedSize(): srcTexture.getSize();
436
437         // Stencil-only texture should be provided if (and only if) the image has a combined DS format
438         DE_ASSERT((tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) == (srcStencilTexture != DE_NULL));
439
440         if (srcStencilTexture != DE_NULL)
441         {
442                 stencilOffset   = static_cast<deUint32>(deAlign32(static_cast<deInt32>(bufferSize), 4));
443                 bufferSize              = stencilOffset + srcStencilTexture->getSize();
444         }
445
446         // Create source buffer
447         {
448                 const VkBufferCreateInfo bufferParams =
449                 {
450                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType      sType;
451                         DE_NULL,                                                                // const void*          pNext;
452                         0u,                                                                             // VkBufferCreateFlags  flags;
453                         bufferSize,                                                             // VkDeviceSize         size;
454                         VK_BUFFER_USAGE_TRANSFER_SRC_BIT,               // VkBufferUsageFlags   usage;
455                         VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode        sharingMode;
456                         0u,                                                                             // deUint32             queueFamilyIndexCount;
457                         DE_NULL,                                                                // const deUint32*      pQueueFamilyIndices;
458                 };
459
460                 buffer          = createBuffer(vk, device, &bufferParams);
461                 bufferAlloc     = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
462                 VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
463         }
464
465         // Write buffer data
466         {
467                 srcTexture.write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()));
468
469                 if (srcStencilTexture != DE_NULL)
470                 {
471                         DE_ASSERT(stencilOffset != 0u);
472
473                         srcStencilTexture->write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()) + stencilOffset);
474
475                         std::vector<VkBufferImageCopy>  stencilCopyRegions = srcStencilTexture->getBufferCopyRegions();
476                         for (size_t regionIdx = 0; regionIdx < stencilCopyRegions.size(); regionIdx++)
477                         {
478                                 VkBufferImageCopy region = stencilCopyRegions[regionIdx];
479                                 region.bufferOffset += stencilOffset;
480
481                                 copyRegions.push_back(region);
482                         }
483                 }
484
485                 flushAlloc(vk, device, *bufferAlloc);
486         }
487
488         copyBufferToImage(vk, device, queue, queueFamilyIndex, *buffer, bufferSize, copyRegions, DE_NULL, imageAspectFlags, srcTexture.getNumLevels(), srcTexture.getArraySize(), destImage, destImageLayout);
489 }
490
491 bool checkSparseImageFormatSupport (const VkPhysicalDevice              physicalDevice,
492                                                                         const InstanceInterface&        instance,
493                                                                         const VkImageCreateInfo&        imageCreateInfo)
494 {
495 #ifndef CTS_USES_VULKANSC
496         const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec =
497                 getPhysicalDeviceSparseImageFormatProperties(instance, physicalDevice, imageCreateInfo.format, imageCreateInfo.imageType, imageCreateInfo.samples, imageCreateInfo.usage, imageCreateInfo.tiling);
498
499         return (sparseImageFormatPropVec.size() != 0);
500 #else
501         DE_UNREF(physicalDevice);
502         DE_UNREF(instance);
503         DE_UNREF(imageCreateInfo);
504         return false;
505 #endif // CTS_USES_VULKANSC
506 }
507
508 void uploadTestTextureInternalSparse (const DeviceInterface&                                    vk,
509                                                                           VkDevice                                                                      device,
510                                                                           const VkPhysicalDevice                                        physicalDevice,
511                                                                           const InstanceInterface&                                      instance,
512                                                                           const VkImageCreateInfo&                                      imageCreateInfo,
513                                                                           VkQueue                                                                       universalQueue,
514                                                                           deUint32                                                                      universalQueueFamilyIndex,
515                                                                           VkQueue                                                                       sparseQueue,
516                                                                           Allocator&                                                            allocator,
517                                                                           std::vector<de::SharedPtr<Allocation> >&      allocations,
518                                                                           const TestTexture&                                            srcTexture,
519                                                                           const TestTexture*                                            srcStencilTexture,
520                                                                           tcu::TextureFormat                                            format,
521                                                                           VkImage                                                                       destImage)
522 {
523         deUint32                                                bufferSize                              = (srcTexture.isCompressed()) ? srcTexture.getCompressedSize(): srcTexture.getSize();
524         const VkImageAspectFlags                imageAspectFlags                = getImageAspectFlags(format);
525         deUint32                                                stencilOffset                   = 0u;
526         const Unique<VkSemaphore>               imageMemoryBindSemaphore(createSemaphore(vk, device));
527         Move<VkCommandPool>                             cmdPool                                 = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, universalQueueFamilyIndex);
528         Move<VkCommandBuffer>                   cmdBuffer                               = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
529         Move<VkFence>                                   fence                                   = createFence(vk, device);
530         std::vector<VkBufferImageCopy>  copyRegions                             = srcTexture.getBufferCopyRegions();
531         Move<VkBuffer>                                  buffer;
532         de::MovePtr<Allocation>                 bufferAlloc;
533
534         // Stencil-only texture should be provided if (and only if) the image has a combined DS format
535         DE_ASSERT((tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) == (srcStencilTexture != DE_NULL));
536
537         if (srcStencilTexture != DE_NULL)
538         {
539                 stencilOffset   = static_cast<deUint32>(deAlign32(static_cast<deInt32>(bufferSize), 4));
540                 bufferSize              = stencilOffset + srcStencilTexture->getSize();
541         }
542
543 #ifndef CTS_USES_VULKANSC
544         allocateAndBindSparseImage (vk, device, physicalDevice, instance, imageCreateInfo, imageMemoryBindSemaphore.get(), sparseQueue, allocator, allocations, format, destImage);
545 #else
546         DE_UNREF(physicalDevice);
547         DE_UNREF(instance);
548         DE_UNREF(sparseQueue);
549         DE_UNREF(allocations);
550 #endif // CTS_USES_VULKANSC
551
552         {
553                 // Create source buffer
554                 const VkBufferCreateInfo bufferParams =
555                 {
556                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
557                         DE_NULL,                                                                        // const void*                  pNext;
558                         0u,                                                                                     // VkBufferCreateFlags  flags;
559                         bufferSize,                                                                     // VkDeviceSize                 size;
560                         VK_BUFFER_USAGE_TRANSFER_SRC_BIT,                       // VkBufferUsageFlags   usage;
561                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
562                         0u,                                                                                     // deUint32                             queueFamilyIndexCount;
563                         DE_NULL,                                                                        // const deUint32*              pQueueFamilyIndices;
564                 };
565
566                 buffer          = createBuffer(vk, device, &bufferParams);
567                 bufferAlloc     = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
568
569                 VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
570         }
571
572         {
573                 // Write buffer data
574                 srcTexture.write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()));
575
576                 if (srcStencilTexture != DE_NULL)
577                 {
578                         DE_ASSERT(stencilOffset != 0u);
579
580                         srcStencilTexture->write(reinterpret_cast<deUint8*>(bufferAlloc->getHostPtr()) + stencilOffset);
581
582                         std::vector<VkBufferImageCopy>  stencilCopyRegions = srcStencilTexture->getBufferCopyRegions();
583                         for (size_t regionIdx = 0; regionIdx < stencilCopyRegions.size(); regionIdx++)
584                         {
585                                 VkBufferImageCopy region = stencilCopyRegions[regionIdx];
586                                 region.bufferOffset += stencilOffset;
587
588                                 copyRegions.push_back(region);
589                         }
590                 }
591
592                 flushAlloc(vk, device, *bufferAlloc);
593         }
594
595         copyBufferToImage(vk, device, universalQueue, universalQueueFamilyIndex, *buffer, bufferSize, copyRegions, &(*imageMemoryBindSemaphore), imageAspectFlags, imageCreateInfo.mipLevels, imageCreateInfo.arrayLayers, destImage);
596 }
597
598 void uploadTestTexture (const DeviceInterface&                  vk,
599                                                 VkDevice                                                device,
600                                                 VkQueue                                                 queue,
601                                                 deUint32                                                queueFamilyIndex,
602                                                 Allocator&                                              allocator,
603                                                 const TestTexture&                              srcTexture,
604                                                 VkImage                                                 destImage,
605                                                 VkImageLayout                                   destImageLayout)
606 {
607         if (tcu::isCombinedDepthStencilType(srcTexture.getTextureFormat().type))
608         {
609                 de::MovePtr<TestTexture> srcDepthTexture;
610                 de::MovePtr<TestTexture> srcStencilTexture;
611
612                 if (tcu::hasDepthComponent(srcTexture.getTextureFormat().order))
613                 {
614                         tcu::TextureFormat format;
615                         switch (srcTexture.getTextureFormat().type)
616                         {
617                                 case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
618                                         format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
619                                         break;
620                                 case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
621                                         format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8_REV);
622                                         break;
623                                 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
624                                         format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
625                                         break;
626                                 default:
627                                         DE_FATAL("Unexpected source texture format.");
628                                         break;
629                         }
630                         srcDepthTexture = srcTexture.copy(format);
631                 }
632
633                 if (tcu::hasStencilComponent(srcTexture.getTextureFormat().order))
634                         srcStencilTexture = srcTexture.copy(tcu::getEffectiveDepthStencilTextureFormat(srcTexture.getTextureFormat(), tcu::Sampler::MODE_STENCIL));
635
636                 uploadTestTextureInternal(vk, device, queue, queueFamilyIndex, allocator, *srcDepthTexture, srcStencilTexture.get(), srcTexture.getTextureFormat(), destImage, destImageLayout);
637         }
638         else
639                 uploadTestTextureInternal(vk, device, queue, queueFamilyIndex, allocator, srcTexture, DE_NULL, srcTexture.getTextureFormat(), destImage, destImageLayout);
640 }
641
642 void uploadTestTextureSparse (const DeviceInterface&                                    vk,
643                                                           VkDevice                                                                      device,
644                                                           const VkPhysicalDevice                                        physicalDevice,
645                                                           const InstanceInterface&                                      instance,
646                                                           const VkImageCreateInfo&                                      imageCreateInfo,
647                                                           VkQueue                                                                       universalQueue,
648                                                           deUint32                                                                      universalQueueFamilyIndex,
649                                                           VkQueue                                                                       sparseQueue,
650                                                           Allocator&                                                            allocator,
651                                                           std::vector<de::SharedPtr<Allocation> >&      allocations,
652                                                           const TestTexture&                                            srcTexture,
653                                                           VkImage                                                                       destImage)
654 {
655         if (tcu::isCombinedDepthStencilType(srcTexture.getTextureFormat().type))
656         {
657                 de::MovePtr<TestTexture> srcDepthTexture;
658                 de::MovePtr<TestTexture> srcStencilTexture;
659
660                 if (tcu::hasDepthComponent(srcTexture.getTextureFormat().order))
661                 {
662                         tcu::TextureFormat format;
663                         switch (srcTexture.getTextureFormat().type)
664                         {
665                                 case tcu::TextureFormat::UNSIGNED_INT_16_8_8:
666                                         format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
667                                         break;
668                                 case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:
669                                         format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8_REV);
670                                         break;
671                                 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
672                                         format = tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
673                                         break;
674                                 default:
675                                         DE_FATAL("Unexpected source texture format.");
676                                         break;
677                         }
678                         srcDepthTexture = srcTexture.copy(format);
679                 }
680
681                 if (tcu::hasStencilComponent(srcTexture.getTextureFormat().order))
682                         srcStencilTexture = srcTexture.copy(tcu::getEffectiveDepthStencilTextureFormat(srcTexture.getTextureFormat(), tcu::Sampler::MODE_STENCIL));
683
684                 uploadTestTextureInternalSparse (vk,
685                                                                                  device,
686                                                                                  physicalDevice,
687                                                                                  instance,
688                                                                                  imageCreateInfo,
689                                                                                  universalQueue,
690                                                                                  universalQueueFamilyIndex,
691                                                                                  sparseQueue,
692                                                                                  allocator,
693                                                                                  allocations,
694                                                                                  *srcDepthTexture,
695                                                                                  srcStencilTexture.get(),
696                                                                                  srcTexture.getTextureFormat(),
697                                                                                  destImage);
698         }
699         else
700         {
701                 uploadTestTextureInternalSparse (vk,
702                                                                                  device,
703                                                                                  physicalDevice,
704                                                                                  instance,
705                                                                                  imageCreateInfo,
706                                                                                  universalQueue,
707                                                                                  universalQueueFamilyIndex,
708                                                                                  sparseQueue,
709                                                                                  allocator,
710                                                                                  allocations,
711                                                                                  srcTexture,
712                                                                                  DE_NULL,
713                                                                                  srcTexture.getTextureFormat(),
714                                                                                  destImage);
715         }
716 }
717
718 // Utilities for test textures
719
720 template<typename TcuTextureType>
721 void allocateLevels (TcuTextureType& texture)
722 {
723         for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
724                 texture.allocLevel(levelNdx);
725 }
726
727 template<typename TcuTextureType>
728 std::vector<tcu::PixelBufferAccess> getLevelsVector (const TcuTextureType& texture)
729 {
730         std::vector<tcu::PixelBufferAccess> levels(texture.getNumLevels());
731
732         for (int levelNdx = 0; levelNdx < texture.getNumLevels(); levelNdx++)
733                 levels[levelNdx] = *reinterpret_cast<const tcu::PixelBufferAccess*>(&texture.getLevel(levelNdx));
734
735         return levels;
736 }
737
738 // TestTexture
739
740 TestTexture::TestTexture (const tcu::TextureFormat& format, int width, int height, int depth)
741 {
742         DE_ASSERT(width >= 1);
743         DE_ASSERT(height >= 1);
744         DE_ASSERT(depth >= 1);
745
746         DE_UNREF(format);
747         DE_UNREF(width);
748         DE_UNREF(height);
749         DE_UNREF(depth);
750 }
751
752 TestTexture::TestTexture (const tcu::CompressedTexFormat& format, int width, int height, int depth)
753 {
754         DE_ASSERT(width >= 1);
755         DE_ASSERT(height >= 1);
756         DE_ASSERT(depth >= 1);
757
758         DE_UNREF(format);
759         DE_UNREF(width);
760         DE_UNREF(height);
761         DE_UNREF(depth);
762 }
763
764 TestTexture::~TestTexture (void)
765 {
766         for (size_t levelNdx = 0; levelNdx < m_compressedLevels.size(); levelNdx++)
767                 delete m_compressedLevels[levelNdx];
768 }
769
770 deUint32 TestTexture::getSize (void) const
771 {
772         std::vector<deUint32>   offsetMultiples;
773         deUint32                                textureSize = 0;
774
775         offsetMultiples.push_back(4);
776         offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
777
778         for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
779         {
780                 for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
781                 {
782                         const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
783                         textureSize = getNextMultiple(offsetMultiples, textureSize);
784                         textureSize += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
785                 }
786         }
787
788         return textureSize;
789 }
790
791 deUint32 TestTexture::getCompressedSize (void) const
792 {
793         if (!isCompressed())
794                 throw tcu::InternalError("Texture is not compressed");
795
796         std::vector<deUint32>   offsetMultiples;
797         deUint32                                textureSize                     = 0;
798
799         offsetMultiples.push_back(4);
800         offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
801
802         for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
803         {
804                 for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
805                 {
806                         textureSize = getNextMultiple(offsetMultiples, textureSize);
807                         textureSize += getCompressedLevel(levelNdx, layerNdx).getDataSize();
808                 }
809         }
810
811         return textureSize;
812 }
813
814 tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer)
815 {
816         DE_ASSERT(level >= 0 && level < getNumLevels());
817         DE_ASSERT(layer >= 0 && layer < getArraySize());
818
819         return *m_compressedLevels[level * getArraySize() + layer];
820 }
821
822 const tcu::CompressedTexture& TestTexture::getCompressedLevel (int level, int layer) const
823 {
824         DE_ASSERT(level >= 0 && level < getNumLevels());
825         DE_ASSERT(layer >= 0 && layer < getArraySize());
826
827         return *m_compressedLevels[level * getArraySize() + layer];
828 }
829
830 std::vector<VkBufferImageCopy> TestTexture::getBufferCopyRegions (void) const
831 {
832         std::vector<deUint32>                   offsetMultiples;
833         std::vector<VkBufferImageCopy>  regions;
834         deUint32                                                layerDataOffset = 0;
835
836         offsetMultiples.push_back(4);
837
838         if (isCompressed())
839         {
840                 offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
841
842                 for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
843                 {
844                         for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
845                         {
846                                 const tcu::CompressedTexture& level = getCompressedLevel(levelNdx, layerNdx);
847                                 tcu::IVec3 blockPixelSize                       = getBlockPixelSize(level.getFormat());
848                                 layerDataOffset                                         = getNextMultiple(offsetMultiples, layerDataOffset);
849
850                                 const VkBufferImageCopy layerRegion =
851                                 {
852                                         layerDataOffset,                                                                                                        // VkDeviceSize                         bufferOffset;
853                                         (deUint32)getNextMultiple(blockPixelSize.x(), level.getWidth()),        // deUint32                                     bufferRowLength;
854                                         (deUint32)getNextMultiple(blockPixelSize.y(), level.getHeight()),       // deUint32                                     bufferImageHeight;
855                                         {                                                                                                                                       // VkImageSubresourceLayers     imageSubresource;
856                                                 VK_IMAGE_ASPECT_COLOR_BIT,
857                                                 (deUint32)levelNdx,
858                                                 (deUint32)layerNdx,
859                                                 1u
860                                         },
861                                         { 0u, 0u, 0u },                                                 // VkOffset3D                           imageOffset;
862                                         {                                                                               // VkExtent3D                           imageExtent;
863                                                 (deUint32)level.getWidth(),
864                                                 (deUint32)level.getHeight(),
865                                                 (deUint32)level.getDepth()
866                                         }
867                                 };
868
869                                 regions.push_back(layerRegion);
870                                 layerDataOffset += level.getDataSize();
871                         }
872                 }
873         }
874         else
875         {
876                 std::vector<VkImageAspectFlags> imageAspects;
877                 tcu::TextureFormat                              textureFormat   = getTextureFormat();
878
879                 if (tcu::hasDepthComponent(textureFormat.order))
880                         imageAspects.push_back(VK_IMAGE_ASPECT_DEPTH_BIT);
881
882                 if (tcu::hasStencilComponent(textureFormat.order))
883                         imageAspects.push_back(VK_IMAGE_ASPECT_STENCIL_BIT);
884
885                 if (imageAspects.empty())
886                         imageAspects.push_back(VK_IMAGE_ASPECT_COLOR_BIT);
887
888                 offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
889
890                 for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
891                 {
892                         for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
893                         {
894                                 const tcu::ConstPixelBufferAccess level = getLevel(levelNdx, layerNdx);
895
896                                 layerDataOffset = getNextMultiple(offsetMultiples, layerDataOffset);
897
898                                 for (size_t aspectIndex = 0; aspectIndex < imageAspects.size(); ++aspectIndex)
899                                 {
900                                         const VkBufferImageCopy layerRegion =
901                                         {
902                                                 layerDataOffset,                                                // VkDeviceSize                         bufferOffset;
903                                                 (deUint32)level.getWidth(),                             // deUint32                                     bufferRowLength;
904                                                 (deUint32)level.getHeight(),                    // deUint32                                     bufferImageHeight;
905                                                 {                                                                               // VkImageSubresourceLayers     imageSubresource;
906                                                         imageAspects[aspectIndex],
907                                                         (deUint32)levelNdx,
908                                                         (deUint32)layerNdx,
909                                                         1u
910                                                 },
911                                                 { 0u, 0u, 0u },                                                 // VkOffset3D                   imageOffset;
912                                                 {                                                                               // VkExtent3D                   imageExtent;
913                                                         (deUint32)level.getWidth(),
914                                                         (deUint32)level.getHeight(),
915                                                         (deUint32)level.getDepth()
916                                                 }
917                                         };
918
919                                         regions.push_back(layerRegion);
920                                 }
921                                 layerDataOffset += level.getWidth() * level.getHeight() * level.getDepth() * level.getFormat().getPixelSize();
922                         }
923                 }
924         }
925
926         return regions;
927 }
928
929 void TestTexture::write (deUint8* destPtr) const
930 {
931         std::vector<deUint32>   offsetMultiples;
932         deUint32                                levelOffset             = 0;
933
934         offsetMultiples.push_back(4);
935
936         if (isCompressed())
937         {
938                 offsetMultiples.push_back(tcu::getBlockSize(getCompressedLevel(0, 0).getFormat()));
939
940                 for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
941                 {
942                         for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
943                         {
944                                 levelOffset = getNextMultiple(offsetMultiples, levelOffset);
945
946                                 const tcu::CompressedTexture&           compressedTex   = getCompressedLevel(levelNdx, layerNdx);
947
948                                 deMemcpy(destPtr + levelOffset, compressedTex.getData(), compressedTex.getDataSize());
949                                 levelOffset += compressedTex.getDataSize();
950                         }
951                 }
952         }
953         else
954         {
955                 offsetMultiples.push_back(getLevel(0, 0).getFormat().getPixelSize());
956
957                 for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
958                 {
959                         for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
960                         {
961                                 levelOffset = getNextMultiple(offsetMultiples, levelOffset);
962
963                                 const tcu::ConstPixelBufferAccess       srcAccess               = getLevel(levelNdx, layerNdx);
964                                 const tcu::PixelBufferAccess            destAccess              (srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), destPtr + levelOffset);
965
966                                 tcu::copy(destAccess, srcAccess);
967                                 levelOffset += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize();
968                         }
969                 }
970         }
971 }
972
973 void TestTexture::copyToTexture (TestTexture& destTexture) const
974 {
975         for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
976                 for (int layerNdx = 0; layerNdx < getArraySize(); layerNdx++)
977                         tcu::copy(destTexture.getLevel(levelNdx, layerNdx), getLevel(levelNdx, layerNdx));
978 }
979
980 void TestTexture::populateLevels (const std::vector<tcu::PixelBufferAccess>& levels)
981 {
982         for (size_t levelNdx = 0; levelNdx < levels.size(); levelNdx++)
983                 TestTexture::fillWithGradient(levels[levelNdx]);
984 }
985
986 void TestTexture::populateCompressedLevels (tcu::CompressedTexFormat format, const std::vector<tcu::PixelBufferAccess>& decompressedLevels)
987 {
988         // Generate random compressed data and update decompressed data
989
990         de::Random random(123);
991
992         for (size_t levelNdx = 0; levelNdx < decompressedLevels.size(); levelNdx++)
993         {
994                 const tcu::PixelBufferAccess    level                           = decompressedLevels[levelNdx];
995                 tcu::CompressedTexture*                 compressedLevel         = new tcu::CompressedTexture(format, level.getWidth(), level.getHeight(), level.getDepth());
996                 deUint8* const                                  compressedData          = (deUint8*)compressedLevel->getData();
997
998                 if (tcu::isAstcFormat(format))
999                 {
1000                         // \todo [2016-01-20 pyry] Comparison doesn't currently handle invalid blocks correctly so we use only valid blocks
1001                         tcu::astc::generateRandomValidBlocks(compressedData, compressedLevel->getDataSize()/tcu::astc::BLOCK_SIZE_BYTES,
1002                                                                                                  format, tcu::TexDecompressionParams::ASTCMODE_LDR, random.getUint32());
1003                 }
1004                 else
1005                 {
1006                         // Generate random compressed data
1007                         // Random initial values cause assertion during the decompression in case of COMPRESSEDTEXFORMAT_ETC1_RGB8 format
1008                         if (format != tcu::COMPRESSEDTEXFORMAT_ETC1_RGB8)
1009                                 for (int byteNdx = 0; byteNdx < compressedLevel->getDataSize(); byteNdx++)
1010                                         compressedData[byteNdx] = 0xFF & random.getUint32();
1011
1012                         // BC7 mode 8 (LSB==0x00) should not be tested as it is underspecified
1013                         if (format == tcu::COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK || format == tcu::COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK)
1014                         {
1015                                 const int blockSize = tcu::getBlockSize(format);
1016
1017                                 for (int byteNdx = 0; byteNdx < compressedLevel->getDataSize(); byteNdx += blockSize)
1018                                         while (compressedData[byteNdx] == 0x00)
1019                                                 compressedData[byteNdx] = 0xFF & random.getUint32();
1020                         }
1021                 }
1022
1023                 m_compressedLevels.push_back(compressedLevel);
1024
1025                 // Store decompressed data
1026                 compressedLevel->decompress(level, tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR));
1027         }
1028 }
1029
1030 void TestTexture::fillWithGradient (const tcu::PixelBufferAccess& levelAccess)
1031 {
1032         const tcu::TextureFormatInfo formatInfo = tcu::getTextureFormatInfo(levelAccess.getFormat());
1033         tcu::fillWithComponentGradients2(levelAccess, formatInfo.valueMin, formatInfo.valueMax);
1034 }
1035
1036 // TestTexture1D
1037
1038 TestTexture1D::TestTexture1D (const tcu::TextureFormat& format, int width)
1039         : TestTexture   (format, width, 1, 1)
1040         , m_texture             (format, width)
1041 {
1042         allocateLevels(m_texture);
1043         TestTexture::populateLevels(getLevelsVector(m_texture));
1044 }
1045
1046 TestTexture1D::TestTexture1D (const tcu::CompressedTexFormat& format, int width)
1047         : TestTexture   (format, width, 1, 1)
1048         , m_texture             (tcu::getUncompressedFormat(format), width)
1049 {
1050         allocateLevels(m_texture);
1051         TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
1052 }
1053
1054 TestTexture1D::~TestTexture1D (void)
1055 {
1056 }
1057
1058 int TestTexture1D::getNumLevels (void) const
1059 {
1060         return m_texture.getNumLevels();
1061 }
1062
1063 tcu::PixelBufferAccess TestTexture1D::getLevel (int level, int layer)
1064 {
1065         DE_ASSERT(layer == 0);
1066         DE_UNREF(layer);
1067         return m_texture.getLevel(level);
1068 }
1069
1070 const tcu::ConstPixelBufferAccess TestTexture1D::getLevel (int level, int layer) const
1071 {
1072         DE_ASSERT(layer == 0);
1073         DE_UNREF(layer);
1074         return m_texture.getLevel(level);
1075 }
1076
1077 const tcu::Texture1D& TestTexture1D::getTexture (void) const
1078 {
1079         return m_texture;
1080 }
1081
1082 tcu::Texture1D& TestTexture1D::getTexture (void)
1083 {
1084         return m_texture;
1085 }
1086
1087 de::MovePtr<TestTexture> TestTexture1D::copy(const tcu::TextureFormat format) const
1088 {
1089         DE_ASSERT(!isCompressed());
1090
1091         de::MovePtr<TestTexture>        texture (new TestTexture1D(format, m_texture.getWidth()));
1092
1093         copyToTexture(*texture);
1094
1095         return texture;
1096 }
1097
1098 // TestTexture1DArray
1099
1100 TestTexture1DArray::TestTexture1DArray (const tcu::TextureFormat& format, int width, int arraySize)
1101         : TestTexture   (format, width, arraySize, 1)
1102         , m_texture             (format, width, arraySize)
1103 {
1104         allocateLevels(m_texture);
1105         TestTexture::populateLevels(getLevelsVector(m_texture));
1106 }
1107
1108 TestTexture1DArray::TestTexture1DArray (const tcu::CompressedTexFormat& format, int width, int arraySize)
1109         : TestTexture   (format, width, arraySize, 1)
1110         , m_texture             (tcu::getUncompressedFormat(format), width, arraySize)
1111 {
1112         allocateLevels(m_texture);
1113
1114         std::vector<tcu::PixelBufferAccess> layers;
1115         for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
1116                 for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
1117                         layers.push_back(getLevel(levelNdx, layerNdx));
1118
1119         TestTexture::populateCompressedLevels(format, layers);
1120 }
1121
1122 TestTexture1DArray::~TestTexture1DArray (void)
1123 {
1124 }
1125
1126 int TestTexture1DArray::getNumLevels (void) const
1127 {
1128         return m_texture.getNumLevels();
1129 }
1130
1131 tcu::PixelBufferAccess TestTexture1DArray::getLevel (int level, int layer)
1132 {
1133         const tcu::PixelBufferAccess    levelLayers     = m_texture.getLevel(level);
1134         const deUint32                                  layerSize       = levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
1135         const deUint32                                  layerOffset     = layerSize * layer;
1136
1137         return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1138 }
1139
1140 const tcu::ConstPixelBufferAccess TestTexture1DArray::getLevel (int level, int layer) const
1141 {
1142         const tcu::ConstPixelBufferAccess       levelLayers     = m_texture.getLevel(level);
1143         const deUint32                                          layerSize       = levelLayers.getWidth() * levelLayers.getFormat().getPixelSize();
1144         const deUint32                                          layerOffset     = layerSize * layer;
1145
1146         return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), 1, 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1147 }
1148
1149 const tcu::Texture1DArray& TestTexture1DArray::getTexture (void) const
1150 {
1151         return m_texture;
1152 }
1153
1154 tcu::Texture1DArray& TestTexture1DArray::getTexture (void)
1155 {
1156         return m_texture;
1157 }
1158
1159 int TestTexture1DArray::getArraySize (void) const
1160 {
1161         return m_texture.getNumLayers();
1162 }
1163
1164 de::MovePtr<TestTexture> TestTexture1DArray::copy(const tcu::TextureFormat format) const
1165 {
1166         DE_ASSERT(!isCompressed());
1167
1168         de::MovePtr<TestTexture>        texture (new TestTexture1DArray(format, m_texture.getWidth(), getArraySize()));
1169
1170         copyToTexture(*texture);
1171
1172         return texture;
1173 }
1174
1175 // TestTexture2D
1176
1177 TestTexture2D::TestTexture2D (const tcu::TextureFormat& format, int width, int height)
1178         : TestTexture   (format, width, height, 1)
1179         , m_texture             (format, width, height)
1180 {
1181         allocateLevels(m_texture);
1182         TestTexture::populateLevels(getLevelsVector(m_texture));
1183 }
1184
1185 TestTexture2D::TestTexture2D (const tcu::TextureFormat& format, int width, int height, int miplevels)
1186         : TestTexture(format, width, height, 1)
1187         , m_texture(format, width, height, miplevels)
1188 {
1189         allocateLevels(m_texture);
1190         TestTexture::populateLevels(getLevelsVector(m_texture));
1191 }
1192
1193
1194 TestTexture2D::TestTexture2D (const tcu::CompressedTexFormat& format, int width, int height)
1195         : TestTexture   (format, width, height, 1)
1196         , m_texture             (tcu::getUncompressedFormat(format), width, height)
1197 {
1198         allocateLevels(m_texture);
1199         TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
1200 }
1201
1202 TestTexture2D::~TestTexture2D (void)
1203 {
1204 }
1205
1206 int TestTexture2D::getNumLevels (void) const
1207 {
1208         return m_texture.getNumLevels();
1209 }
1210
1211 tcu::PixelBufferAccess TestTexture2D::getLevel (int level, int layer)
1212 {
1213         DE_ASSERT(layer == 0);
1214         DE_UNREF(layer);
1215         return m_texture.getLevel(level);
1216 }
1217
1218 const tcu::ConstPixelBufferAccess TestTexture2D::getLevel (int level, int layer) const
1219 {
1220         DE_ASSERT(layer == 0);
1221         DE_UNREF(layer);
1222         return m_texture.getLevel(level);
1223 }
1224
1225 const tcu::Texture2D& TestTexture2D::getTexture (void) const
1226 {
1227         return m_texture;
1228 }
1229
1230 tcu::Texture2D& TestTexture2D::getTexture (void)
1231 {
1232         return m_texture;
1233 }
1234
1235 de::MovePtr<TestTexture> TestTexture2D::copy(const tcu::TextureFormat format) const
1236 {
1237         DE_ASSERT(!isCompressed());
1238
1239         de::MovePtr<TestTexture>        texture (new TestTexture2D(format, m_texture.getWidth(), m_texture.getHeight(), m_texture.getNumLevels()));
1240
1241         copyToTexture(*texture);
1242
1243         return texture;
1244 }
1245
1246 // TestTexture2DArray
1247
1248 TestTexture2DArray::TestTexture2DArray (const tcu::TextureFormat& format, int width, int height, int arraySize)
1249         : TestTexture   (format, width, height, arraySize)
1250         , m_texture             (format, width, height, arraySize)
1251 {
1252         allocateLevels(m_texture);
1253         TestTexture::populateLevels(getLevelsVector(m_texture));
1254 }
1255
1256 TestTexture2DArray::TestTexture2DArray (const tcu::CompressedTexFormat& format, int width, int height, int arraySize)
1257         : TestTexture   (format, width, height, arraySize)
1258         , m_texture             (tcu::getUncompressedFormat(format), width, height, arraySize)
1259 {
1260         allocateLevels(m_texture);
1261
1262         std::vector<tcu::PixelBufferAccess> layers;
1263         for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
1264                 for (int layerNdx = 0; layerNdx < m_texture.getNumLayers(); layerNdx++)
1265                         layers.push_back(getLevel(levelNdx, layerNdx));
1266
1267         TestTexture::populateCompressedLevels(format, layers);
1268 }
1269
1270 TestTexture2DArray::~TestTexture2DArray (void)
1271 {
1272 }
1273
1274 int TestTexture2DArray::getNumLevels (void) const
1275 {
1276         return m_texture.getNumLevels();
1277 }
1278
1279 tcu::PixelBufferAccess TestTexture2DArray::getLevel (int level, int layer)
1280 {
1281         const tcu::PixelBufferAccess    levelLayers     = m_texture.getLevel(level);
1282         const deUint32                                  layerSize       = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1283         const deUint32                                  layerOffset     = layerSize * layer;
1284
1285         return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1286 }
1287
1288 const tcu::ConstPixelBufferAccess TestTexture2DArray::getLevel (int level, int layer) const
1289 {
1290         const tcu::ConstPixelBufferAccess       levelLayers     = m_texture.getLevel(level);
1291         const deUint32                                          layerSize       = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1292         const deUint32                                          layerOffset     = layerSize * layer;
1293
1294         return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1295 }
1296
1297 const tcu::Texture2DArray& TestTexture2DArray::getTexture (void) const
1298 {
1299         return m_texture;
1300 }
1301
1302 tcu::Texture2DArray& TestTexture2DArray::getTexture (void)
1303 {
1304         return m_texture;
1305 }
1306
1307 int TestTexture2DArray::getArraySize (void) const
1308 {
1309         return m_texture.getNumLayers();
1310 }
1311
1312 de::MovePtr<TestTexture> TestTexture2DArray::copy(const tcu::TextureFormat format) const
1313 {
1314         DE_ASSERT(!isCompressed());
1315
1316         de::MovePtr<TestTexture>        texture (new TestTexture2DArray(format, m_texture.getWidth(), m_texture.getHeight(), getArraySize()));
1317
1318         copyToTexture(*texture);
1319
1320         return texture;
1321 }
1322
1323 // TestTexture3D
1324
1325 TestTexture3D::TestTexture3D (const tcu::TextureFormat& format, int width, int height, int depth)
1326         : TestTexture   (format, width, height, depth)
1327         , m_texture             (format, width, height, depth)
1328 {
1329         allocateLevels(m_texture);
1330         TestTexture::populateLevels(getLevelsVector(m_texture));
1331 }
1332
1333 TestTexture3D::TestTexture3D (const tcu::CompressedTexFormat& format, int width, int height, int depth)
1334         : TestTexture   (format, width, height, depth)
1335         , m_texture             (tcu::getUncompressedFormat(format), width, height, depth)
1336 {
1337         allocateLevels(m_texture);
1338         TestTexture::populateCompressedLevels(format, getLevelsVector(m_texture));
1339 }
1340
1341 TestTexture3D::~TestTexture3D (void)
1342 {
1343 }
1344
1345 int TestTexture3D::getNumLevels (void) const
1346 {
1347         return m_texture.getNumLevels();
1348 }
1349
1350 tcu::PixelBufferAccess TestTexture3D::getLevel (int level, int layer)
1351 {
1352         DE_ASSERT(layer == 0);
1353         DE_UNREF(layer);
1354         return m_texture.getLevel(level);
1355 }
1356
1357 const tcu::ConstPixelBufferAccess TestTexture3D::getLevel (int level, int layer) const
1358 {
1359         DE_ASSERT(layer == 0);
1360         DE_UNREF(layer);
1361         return m_texture.getLevel(level);
1362 }
1363
1364 const tcu::Texture3D& TestTexture3D::getTexture (void) const
1365 {
1366         return m_texture;
1367 }
1368
1369 tcu::Texture3D& TestTexture3D::getTexture (void)
1370 {
1371         return m_texture;
1372 }
1373
1374 de::MovePtr<TestTexture> TestTexture3D::copy(const tcu::TextureFormat format) const
1375 {
1376         DE_ASSERT(!isCompressed());
1377
1378         de::MovePtr<TestTexture>        texture (new TestTexture3D(format, m_texture.getWidth(), m_texture.getHeight(), m_texture.getDepth()));
1379
1380         copyToTexture(*texture);
1381
1382         return texture;
1383 }
1384
1385 // TestTextureCube
1386
1387 const static tcu::CubeFace tcuFaceMapping[tcu::CUBEFACE_LAST] =
1388 {
1389         tcu::CUBEFACE_POSITIVE_X,
1390         tcu::CUBEFACE_NEGATIVE_X,
1391         tcu::CUBEFACE_POSITIVE_Y,
1392         tcu::CUBEFACE_NEGATIVE_Y,
1393         tcu::CUBEFACE_POSITIVE_Z,
1394         tcu::CUBEFACE_NEGATIVE_Z
1395 };
1396
1397 TestTextureCube::TestTextureCube (const tcu::TextureFormat& format, int size)
1398         : TestTexture   (format, size, size, 1)
1399         , m_texture             (format, size)
1400 {
1401         for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
1402         {
1403                 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1404                 {
1405                         m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
1406                         TestTexture::fillWithGradient(m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]));
1407                 }
1408         }
1409 }
1410
1411 TestTextureCube::TestTextureCube (const tcu::CompressedTexFormat& format, int size)
1412         : TestTexture   (format, size, size, 1)
1413         , m_texture             (tcu::getUncompressedFormat(format), size)
1414 {
1415         std::vector<tcu::PixelBufferAccess> levels(m_texture.getNumLevels() * tcu::CUBEFACE_LAST);
1416
1417         for (int levelNdx = 0; levelNdx < getNumLevels(); levelNdx++)
1418         {
1419                 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1420                 {
1421                         m_texture.allocLevel(tcuFaceMapping[faceNdx], levelNdx);
1422                         levels[levelNdx * tcu::CUBEFACE_LAST + faceNdx] = m_texture.getLevelFace(levelNdx, tcuFaceMapping[faceNdx]);
1423                 }
1424         }
1425
1426         TestTexture::populateCompressedLevels(format, levels);
1427 }
1428
1429 TestTextureCube::~TestTextureCube (void)
1430 {
1431 }
1432
1433 int TestTextureCube::getNumLevels (void) const
1434 {
1435         return m_texture.getNumLevels();
1436 }
1437
1438 tcu::PixelBufferAccess TestTextureCube::getLevel (int level, int layer)
1439 {
1440         return m_texture.getLevelFace(level, tcuFaceMapping[layer]);
1441 }
1442
1443 const tcu::ConstPixelBufferAccess TestTextureCube::getLevel (int level, int layer) const
1444 {
1445         return m_texture.getLevelFace(level, tcuFaceMapping[layer]);
1446 }
1447
1448 int TestTextureCube::getArraySize (void) const
1449 {
1450         return (int)tcu::CUBEFACE_LAST;
1451 }
1452
1453 const tcu::TextureCube& TestTextureCube::getTexture (void) const
1454 {
1455         return m_texture;
1456 }
1457
1458 tcu::TextureCube& TestTextureCube::getTexture (void)
1459 {
1460         return m_texture;
1461 }
1462
1463 de::MovePtr<TestTexture> TestTextureCube::copy(const tcu::TextureFormat format) const
1464 {
1465         DE_ASSERT(!isCompressed());
1466
1467         de::MovePtr<TestTexture>        texture (new TestTextureCube(format, m_texture.getSize()));
1468
1469         copyToTexture(*texture);
1470
1471         return texture;
1472 }
1473
1474 // TestTextureCubeArray
1475
1476 TestTextureCubeArray::TestTextureCubeArray (const tcu::TextureFormat& format, int size, int arraySize)
1477         : TestTexture   (format, size, size, arraySize)
1478         , m_texture             (format, size, arraySize)
1479 {
1480         allocateLevels(m_texture);
1481         TestTexture::populateLevels(getLevelsVector(m_texture));
1482 }
1483
1484 TestTextureCubeArray::TestTextureCubeArray (const tcu::CompressedTexFormat& format, int size, int arraySize)
1485         : TestTexture   (format, size, size, arraySize)
1486         , m_texture             (tcu::getUncompressedFormat(format), size, arraySize)
1487 {
1488         DE_ASSERT(arraySize % 6 == 0);
1489
1490         allocateLevels(m_texture);
1491
1492         std::vector<tcu::PixelBufferAccess> layers;
1493         for (int levelNdx = 0; levelNdx < m_texture.getNumLevels(); levelNdx++)
1494                 for (int layerNdx = 0; layerNdx < m_texture.getDepth(); layerNdx++)
1495                         layers.push_back(getLevel(levelNdx, layerNdx));
1496
1497         TestTexture::populateCompressedLevels(format, layers);
1498 }
1499
1500 TestTextureCubeArray::~TestTextureCubeArray (void)
1501 {
1502 }
1503
1504 int TestTextureCubeArray::getNumLevels (void) const
1505 {
1506         return m_texture.getNumLevels();
1507 }
1508
1509 tcu::PixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer)
1510 {
1511         const tcu::PixelBufferAccess    levelLayers     = m_texture.getLevel(level);
1512         const deUint32                                  layerSize       = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1513         const deUint32                                  layerOffset     = layerSize * layer;
1514
1515         return tcu::PixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1516 }
1517
1518 const tcu::ConstPixelBufferAccess TestTextureCubeArray::getLevel (int level, int layer) const
1519 {
1520         const tcu::ConstPixelBufferAccess       levelLayers     = m_texture.getLevel(level);
1521         const deUint32                                          layerSize       = levelLayers.getWidth() * levelLayers.getHeight() * levelLayers.getFormat().getPixelSize();
1522         const deUint32                                          layerOffset     = layerSize * layer;
1523
1524         return tcu::ConstPixelBufferAccess(levelLayers.getFormat(), levelLayers.getWidth(), levelLayers.getHeight(), 1, (deUint8*)levelLayers.getDataPtr() + layerOffset);
1525 }
1526
1527 int TestTextureCubeArray::getArraySize (void) const
1528 {
1529         return m_texture.getDepth();
1530 }
1531
1532 const tcu::TextureCubeArray& TestTextureCubeArray::getTexture (void) const
1533 {
1534         return m_texture;
1535 }
1536
1537 tcu::TextureCubeArray& TestTextureCubeArray::getTexture (void)
1538 {
1539         return m_texture;
1540 }
1541
1542 de::MovePtr<TestTexture> TestTextureCubeArray::copy(const tcu::TextureFormat format) const
1543 {
1544         DE_ASSERT(!isCompressed());
1545
1546         de::MovePtr<TestTexture>        texture (new TestTextureCubeArray(format, m_texture.getSize(), getArraySize()));
1547
1548         copyToTexture(*texture);
1549
1550         return texture;
1551 }
1552
1553 } // pipeline
1554 } // vkt