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