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