xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/image/vktImageHostImageCopyTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google LLC.
7  * Copyright (c) 2022 LunarG, Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Tests for VK_EXT_host_image_copy
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktImageHostImageCopyTests.hpp"
27 
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 
31 #include "vkCmdUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkImageWithMemory.hpp"
40 #include "vkBufferWithMemory.hpp"
41 #include "vktImageTestsUtil.hpp"
42 #include "ycbcr/vktYCbCrUtil.hpp"
43 
44 #include "tcuTestLog.hpp"
45 #include "tcuVectorUtil.hpp"
46 #include "tcuTextureUtil.hpp"
47 
48 #include <set>
49 
50 namespace vkt
51 {
52 namespace image
53 {
54 namespace
55 {
56 
57 using namespace vk;
58 
getAspectFlags(vk::VkFormat format)59 vk::VkImageAspectFlags getAspectFlags(vk::VkFormat format)
60 {
61     if (isCompressedFormat(format))
62     {
63         return vk::VK_IMAGE_ASPECT_COLOR_BIT;
64     }
65 
66     const auto sampledFormat = mapVkFormat(format);
67     if (sampledFormat.order == tcu::TextureFormat::S)
68     {
69         return vk::VK_IMAGE_ASPECT_STENCIL_BIT;
70     }
71     if (sampledFormat.order == tcu::TextureFormat::D || sampledFormat.order == tcu::TextureFormat::DS)
72     {
73         return vk::VK_IMAGE_ASPECT_DEPTH_BIT;
74     }
75     return vk::VK_IMAGE_ASPECT_COLOR_BIT;
76 }
77 
getChannelSize(vk::VkFormat format)78 uint32_t getChannelSize(vk::VkFormat format)
79 {
80     const auto tcuFormat =
81         isCompressedFormat(format) ? tcu::getUncompressedFormat(mapVkCompressedFormat(format)) : mapVkFormat(format);
82     if (tcuFormat.order != tcu::TextureFormat::D && tcuFormat.order != tcu::TextureFormat::S &&
83         tcuFormat.order != tcu::TextureFormat::DS)
84     {
85         return tcu::getChannelSize(tcuFormat.type);
86     }
87     switch (format)
88     {
89     case vk::VK_FORMAT_D24_UNORM_S8_UINT:
90         return 4;
91     case vk::VK_FORMAT_D32_SFLOAT:
92         return 4;
93     case vk::VK_FORMAT_D16_UNORM:
94         return 2;
95     case vk::VK_FORMAT_S8_UINT:
96         return 1;
97     default:
98         break;
99     }
100     DE_ASSERT(0);
101     return 0;
102 }
103 
getNumChannels(vk::VkFormat format)104 uint32_t getNumChannels(vk::VkFormat format)
105 {
106     const auto tcuFormat =
107         isCompressedFormat(format) ? tcu::getUncompressedFormat(mapVkCompressedFormat(format)) : mapVkFormat(format);
108     if (tcuFormat.order != tcu::TextureFormat::D && tcuFormat.order != tcu::TextureFormat::S &&
109         tcuFormat.order != tcu::TextureFormat::DS)
110     {
111         return tcu::getNumUsedChannels(tcuFormat.order);
112     }
113     return 1;
114 }
115 
generateData(void * ptr,uint32_t size,vk::VkFormat format)116 void generateData(void *ptr, uint32_t size, vk::VkFormat format)
117 {
118     if (isDepthStencilFormat(format))
119     {
120         de::Random randomGen(deInt32Hash((uint32_t)format) ^ deInt32Hash((uint32_t)size));
121         if (format == VK_FORMAT_D16_UNORM)
122         {
123             ycbcr::fillRandomNoNaN(&randomGen, (uint8_t *)ptr, size, VK_FORMAT_R16_UNORM);
124         }
125         else
126         {
127             ycbcr::fillRandomNoNaN(&randomGen, (uint8_t *)ptr, size, VK_FORMAT_R32_SFLOAT);
128         }
129     }
130     else if (isCompressedFormat(format))
131     {
132         memset(ptr, 255, size);
133     }
134     else
135     {
136         de::Random randomGen(deInt32Hash((uint32_t)format) ^ deInt32Hash((uint32_t)size));
137         ycbcr::fillRandomNoNaN(&randomGen, (uint8_t *)ptr, size, format);
138     }
139 }
140 
getHostImageCopyProperties(const vk::InstanceDriver & instanceDriver,VkPhysicalDevice physicalDevice,vk::VkPhysicalDeviceHostImageCopyPropertiesEXT * hostImageCopyProperties)141 void getHostImageCopyProperties(const vk::InstanceDriver &instanceDriver, VkPhysicalDevice physicalDevice,
142                                 vk::VkPhysicalDeviceHostImageCopyPropertiesEXT *hostImageCopyProperties)
143 {
144     vk::VkPhysicalDeviceProperties properties;
145     deMemset(&properties, 0, sizeof(vk::VkPhysicalDeviceProperties));
146     vk::VkPhysicalDeviceProperties2 properties2 = {
147         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType                    sType
148         hostImageCopyProperties,                            // const void*                        pNext
149         properties                                          // VkPhysicalDeviceProperties        properties
150     };
151     instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &properties2);
152 }
153 
isBlockCompressedFormat(vk::VkFormat format)154 bool isBlockCompressedFormat(vk::VkFormat format)
155 {
156     switch (format)
157     {
158     case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
159     case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
160     case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
161     case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
162     case VK_FORMAT_BC2_UNORM_BLOCK:
163     case VK_FORMAT_BC2_SRGB_BLOCK:
164     case VK_FORMAT_BC3_UNORM_BLOCK:
165     case VK_FORMAT_BC3_SRGB_BLOCK:
166     case VK_FORMAT_BC4_UNORM_BLOCK:
167     case VK_FORMAT_BC4_SNORM_BLOCK:
168     case VK_FORMAT_BC5_UNORM_BLOCK:
169     case VK_FORMAT_BC5_SNORM_BLOCK:
170     case VK_FORMAT_BC6H_UFLOAT_BLOCK:
171     case VK_FORMAT_BC6H_SFLOAT_BLOCK:
172     case VK_FORMAT_BC7_UNORM_BLOCK:
173     case VK_FORMAT_BC7_SRGB_BLOCK:
174         return true;
175     default:
176         break;
177     }
178     return false;
179 }
180 
checkSupportedFormatFeatures(const vk::InstanceDriver & vki,VkPhysicalDevice physicalDevice,vk::VkFormat format,vk::VkImageTiling tiling,uint64_t * outDrmModifier)181 void checkSupportedFormatFeatures(const vk::InstanceDriver &vki, VkPhysicalDevice physicalDevice, vk::VkFormat format,
182                                   vk::VkImageTiling tiling, uint64_t *outDrmModifier)
183 {
184     vk::VkDrmFormatModifierPropertiesList2EXT drmList = vk::initVulkanStructure();
185     vk::VkFormatProperties3 formatProperties3         = tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ?
186                                                             vk::initVulkanStructure(&drmList) :
187                                                             vk::initVulkanStructure();
188     vk::VkFormatProperties2 formatProperties2         = vk::initVulkanStructure(&formatProperties3);
189     vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties2);
190     std::vector<vk::VkDrmFormatModifierProperties2EXT> modifiers(drmList.drmFormatModifierCount);
191 
192     if (tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
193     {
194         if (drmList.drmFormatModifierCount == 0)
195             TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for drm format modifier.");
196         drmList.pDrmFormatModifierProperties = modifiers.data();
197         vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties2);
198 
199         bool modifierFound = false;
200         for (uint32_t i = 0; i < drmList.drmFormatModifierCount; ++i)
201         {
202             if (drmList.pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures &
203                 vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT)
204             {
205                 *outDrmModifier = drmList.pDrmFormatModifierProperties[i].drmFormatModifier;
206                 return;
207             }
208         }
209 
210         if (!modifierFound)
211             TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for drm format modifier.");
212     }
213     else
214     {
215         if (tiling == vk::VK_IMAGE_TILING_LINEAR &&
216             (formatProperties3.linearTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
217             TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for optimal tiling.");
218         if (tiling == vk::VK_IMAGE_TILING_OPTIMAL &&
219             (formatProperties3.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
220             TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for optimal tiling.");
221     }
222 }
223 
224 enum Command
225 {
226     DRAW,
227     DISPATCH,
228 };
229 
230 struct TestParameters
231 {
232     bool hostCopyMemoryToImage;
233     bool hostCopyImageToMemory;
234     bool hostTransferLayout;
235     bool outputImageHostTransition;
236     bool memcpyFlag;
237     bool dynamicRendering;
238     Command command;
239     vk::VkFormat imageSampledFormat;
240     vk::VkImageLayout srcLayout;
241     vk::VkImageLayout dstLayout;
242     vk::VkImageLayout intermediateLayout;
243     vk::VkImageTiling sampledTiling;
244     vk::VkFormat imageOutputFormat;
245     vk::VkExtent3D imageSize;
246     bool sparse;
247     uint32_t mipLevel;
248     uint32_t regionsCount;
249     uint32_t padding;
250 };
251 
252 class HostImageCopyTestInstance : public vkt::TestInstance
253 {
254 public:
HostImageCopyTestInstance(vkt::Context & context,const TestParameters & parameters)255     HostImageCopyTestInstance(vkt::Context &context, const TestParameters &parameters)
256         : vkt::TestInstance(context)
257         , m_parameters(parameters)
258     {
259     }
260     void transitionImageLayout(const Move<vk::VkCommandBuffer> *cmdBuffer, vk::VkImage image,
261                                vk::VkImageLayout oldLayout, vk::VkImageLayout newLayout,
262                                vk::VkImageSubresourceRange subresourceRange);
263     void copyMemoryToImage(const std::vector<uint8_t> testData, vk::VkImage image, uint32_t texelSize,
264                            const vk::VkImageSubresourceLayers subresourceLayers, int32_t xOffset, int32_t yOffset,
265                            uint32_t width, uint32_t height);
266 
267 private:
268     tcu::TestStatus iterate(void);
269 
270     const TestParameters m_parameters;
271 };
272 
transitionImageLayout(const Move<vk::VkCommandBuffer> * cmdBuffer,vk::VkImage image,vk::VkImageLayout oldLayout,vk::VkImageLayout newLayout,vk::VkImageSubresourceRange subresourceRange)273 void HostImageCopyTestInstance::transitionImageLayout(const Move<vk::VkCommandBuffer> *cmdBuffer, vk::VkImage image,
274                                                       vk::VkImageLayout oldLayout, vk::VkImageLayout newLayout,
275                                                       vk::VkImageSubresourceRange subresourceRange)
276 {
277     const DeviceInterface &vk = m_context.getDeviceInterface();
278     const vk::VkDevice device = m_context.getDevice();
279     const vk::VkQueue queue   = m_context.getUniversalQueue();
280 
281     if (m_parameters.hostTransferLayout)
282     {
283         vk::VkHostImageLayoutTransitionInfoEXT transition = {
284             vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT, // VkStructureType sType;
285             DE_NULL,                                                     // const void* pNext;
286             image,                                                       // VkImage image;
287             oldLayout,                                                   // VkImageLayout oldLayout;
288             newLayout,                                                   // VkImageLayout newLayout;
289             subresourceRange                                             // VkImageSubresourceRange subresourceRange;
290         };
291         vk.transitionImageLayoutEXT(device, 1, &transition);
292     }
293     else
294     {
295         vk::beginCommandBuffer(vk, **cmdBuffer, 0u);
296         auto imageMemoryBarrier =
297             makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, oldLayout, newLayout, image, subresourceRange);
298         vk.cmdPipelineBarrier(**cmdBuffer, vk::VK_PIPELINE_STAGE_NONE, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
299                               DE_NULL, 0u, DE_NULL, 1, &imageMemoryBarrier);
300         vk::endCommandBuffer(vk, **cmdBuffer);
301         vk::submitCommandsAndWait(vk, device, queue, **cmdBuffer);
302     }
303 }
304 
copyMemoryToImage(const std::vector<uint8_t> testData,vk::VkImage image,uint32_t texelSize,const vk::VkImageSubresourceLayers subresourceLayers,int32_t xOffset,int32_t yOffset,uint32_t width,uint32_t height)305 void HostImageCopyTestInstance::copyMemoryToImage(const std::vector<uint8_t> testData, vk::VkImage image,
306                                                   uint32_t texelSize,
307                                                   const vk::VkImageSubresourceLayers subresourceLayers, int32_t xOffset,
308                                                   int32_t yOffset, uint32_t width, uint32_t height)
309 {
310     const DeviceInterface &vk = m_context.getDeviceInterface();
311     const vk::VkDevice device = m_context.getDevice();
312     std::vector<uint8_t> data(texelSize * width * height);
313     const uint32_t imageWidth = m_parameters.imageSize.width;
314     for (uint32_t i = 0; i < height; ++i)
315     {
316         memcpy(&data[i * width * texelSize], &testData[((yOffset + i) * imageWidth + xOffset) * texelSize],
317                width * texelSize);
318     }
319 
320     const uint32_t regionsCount = m_parameters.regionsCount > height ? m_parameters.regionsCount : 1u;
321     std::vector<vk::VkMemoryToImageCopyEXT> regions;
322 
323     for (uint32_t i = 0; i < regionsCount; ++i)
324     {
325         vk::VkOffset3D offset = {xOffset, (int32_t)(yOffset + height / regionsCount * i), 0};
326         vk::VkExtent3D extent = {width, height / regionsCount, 1};
327         if (i == regionsCount - 1)
328             extent.height = height - height / regionsCount * i;
329 
330         if (extent.height == 0)
331             continue;
332 
333         uint32_t dataOffset = width * (height / regionsCount * i) * texelSize;
334 
335         const vk::VkMemoryToImageCopyEXT region = {
336             vk::VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT, // VkStructureType sType;
337             DE_NULL,                                        // const void* pNext;
338             &data[dataOffset],                              // const void* memoryHostPointer;
339             0,                                              // uint32_t memoryRowLength;
340             0,                                              // uint32_t memoryImageHeight;
341             subresourceLayers,                              // VkImageSubresourceLayers imageSubresource;
342             offset,                                         // VkOffset3D imageOffset;
343             extent                                          // VkExtent3D imageExtent;
344         };
345         regions.push_back(region);
346     }
347 
348     vk::VkCopyMemoryToImageInfoEXT copyMemoryToImageInfo = {
349         vk::VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT, // VkStructureType sType;
350         DE_NULL,                                             // const void* pNext;
351         0u,                                                  // VkMemoryImageCopyFlagsEXT flags;
352         image,                                               // VkImage dstImage;
353         m_parameters.dstLayout,                              // VkImageLayout dstImageLayout;
354         (uint32_t)regions.size(),                            // uint32_t regionCount;
355         regions.data(),                                      // const VkMemoryToImageCopyEXT* pRegions;
356     };
357 
358     vk.copyMemoryToImageEXT(device, &copyMemoryToImageInfo);
359 }
360 
iterate(void)361 tcu::TestStatus HostImageCopyTestInstance::iterate(void)
362 {
363     const InstanceInterface &vki              = m_context.getInstanceInterface();
364     const DeviceInterface &vk                 = m_context.getDeviceInterface();
365     const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
366     const vk::VkDevice device                 = m_context.getDevice();
367     const auto &deviceExtensions              = m_context.getDeviceExtensions();
368     const uint32_t queueFamilyIndex           = m_context.getUniversalQueueFamilyIndex();
369     const vk::VkQueue queue                   = m_context.getUniversalQueue();
370     auto &alloc                               = m_context.getDefaultAllocator();
371     tcu::TestLog &log                         = m_context.getTestContext().getLog();
372 
373     std::stringstream commandsLog;
374 
375     const Move<vk::VkCommandPool> cmdPool(
376         createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
377     const Move<vk::VkCommandBuffer> cmdBuffer(
378         allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
379 
380     const vk::VkExtent3D imageSize    = {m_parameters.imageSize.width * (uint32_t)dePow(2, m_parameters.mipLevel),
381                                          m_parameters.imageSize.height * (uint32_t)dePow(2, m_parameters.mipLevel), 1};
382     const vk::VkExtent3D mipImageSize = {m_parameters.imageSize.width, m_parameters.imageSize.height, 1};
383 
384     const vk::VkRect2D renderArea = vk::makeRect2D(0, 0, mipImageSize.width, mipImageSize.height);
385 
386     const auto sampledChannelSize = getChannelSize(m_parameters.imageSampledFormat);
387     const auto sampledNumChannels = getNumChannels(m_parameters.imageSampledFormat);
388     const auto sampledBufferCount = mipImageSize.width * mipImageSize.height * sampledNumChannels;
389     const auto sampledBufferSize  = sampledBufferCount * sampledChannelSize;
390 
391     const auto outputFormat      = mapVkFormat(m_parameters.imageOutputFormat);
392     const auto outputChannelSize = getChannelSize(m_parameters.imageOutputFormat);
393     const auto outputNumChannels = getNumUsedChannels(m_parameters.imageOutputFormat);
394     const auto outputBufferCount = mipImageSize.width * mipImageSize.height * outputNumChannels;
395     const auto outputBufferSize  = outputBufferCount * outputChannelSize;
396 
397     vk::VkImage sampledImage     = VK_NULL_HANDLE;
398     vk::VkImage sampledImageCopy = VK_NULL_HANDLE;
399     de::MovePtr<ImageWithMemory> sampledImageWithMemory;
400     de::MovePtr<SparseImage> sparseSampledImage;
401     de::MovePtr<SparseImage> sparseSampledImageCopy;
402     de::MovePtr<ImageWithMemory> sampledImageWithMemoryCopy;
403     de::MovePtr<ImageWithMemory> outputImage;
404     Move<vk::VkImageView> sampledImageView;
405     Move<vk::VkImageView> sampledImageViewCopy;
406     Move<vk::VkImageView> outputImageView;
407 
408     const vk::VkImageAspectFlags sampledAspect      = getAspectFlags(m_parameters.imageSampledFormat);
409     const vk::VkComponentMapping componentMapping   = makeComponentMappingRGBA();
410     const vk::VkOffset3D imageOffset                = makeOffset3D(0, 0, 0);
411     const vk::VkImageSubresource sampledSubresource = makeImageSubresource(sampledAspect, m_parameters.mipLevel, 0u);
412     const vk::VkImageSubresourceRange sampledSubresourceRange =
413         makeImageSubresourceRange(sampledAspect, m_parameters.mipLevel, 1u, 0u, 1u);
414     const vk::VkImageSubresourceLayers sampledSubresourceLayers =
415         makeImageSubresourceLayers(sampledAspect, m_parameters.mipLevel, 0u, 1u);
416     const auto outputSubresourceRange =
417         makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, m_parameters.mipLevel, 1u, 0u, 1u);
418     const vk::VkImageSubresourceLayers outputSubresourceLayers =
419         makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, m_parameters.mipLevel, 0u, 1u);
420 
421     std::vector<uint8_t> testData(sampledBufferSize);
422     generateData(testData.data(), sampledBufferSize, m_parameters.imageSampledFormat);
423 
424     // Create sampled image
425     {
426         vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_SAMPLED_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
427         if (m_parameters.hostCopyMemoryToImage || m_parameters.hostCopyImageToMemory || m_parameters.memcpyFlag ||
428             m_parameters.hostTransferLayout)
429             usage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
430         if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
431             usage |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
432         else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
433             usage |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
434         else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
435             usage |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
436 
437         vk::VkImageCreateInfo createInfo = {
438             vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
439             DE_NULL,                                 // const void*                pNext
440             0u,                                      // VkImageCreateFlags        flags
441             vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
442             m_parameters.imageSampledFormat,         // VkFormat                    format
443             imageSize,                               // VkExtent3D                extent
444             m_parameters.mipLevel + 1,               // uint32_t                    mipLevels
445             1u,                                      // uint32_t                    arrayLayers
446             vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
447             m_parameters.sampledTiling,              // VkImageTiling            tiling
448             usage,                                   // VkImageUsageFlags        usage
449             vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
450             0,                                       // uint32_t                    queueFamilyIndexCount
451             DE_NULL,                                 // const uint32_t*            pQueueFamilyIndices
452             vk::VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
453         };
454 
455         if (m_parameters.sparse)
456         {
457             createInfo.flags |= (vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT | vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT);
458             sparseSampledImage = de::MovePtr<SparseImage>(new SparseImage(vk, device, physicalDevice, vki, createInfo,
459                                                                           m_context.getSparseQueue(), alloc,
460                                                                           mapVkFormat(createInfo.format)));
461             sampledImage       = **sparseSampledImage;
462             if (m_parameters.memcpyFlag)
463             {
464                 sparseSampledImageCopy = de::MovePtr<SparseImage>(
465                     new SparseImage(vk, device, physicalDevice, vki, createInfo, m_context.getSparseQueue(), alloc,
466                                     mapVkFormat(createInfo.format)));
467                 sampledImageCopy = **sparseSampledImageCopy;
468             }
469         }
470         else
471         {
472             sampledImageWithMemory = de::MovePtr<ImageWithMemory>(
473                 new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
474             sampledImage = **sampledImageWithMemory;
475             if (m_parameters.memcpyFlag)
476             {
477                 sampledImageWithMemoryCopy = de::MovePtr<ImageWithMemory>(
478                     new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
479                 sampledImageCopy = **sampledImageWithMemoryCopy;
480             }
481         }
482 
483         vk::VkImageViewCreateInfo imageViewCreateInfo = {
484             vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
485             DE_NULL,                                      // const void* pNext;
486             (vk::VkImageViewCreateFlags)0u,               // VkImageViewCreateFlags flags;
487             sampledImage,                                 // VkImage image;
488             vk::VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
489             m_parameters.imageSampledFormat,              // VkFormat format;
490             componentMapping,                             // VkComponentMapping components;
491             sampledSubresourceRange                       // VkImageSubresourceRange subresourceRange;
492         };
493         sampledImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
494         if (m_parameters.memcpyFlag)
495         {
496             imageViewCreateInfo.image = sampledImageCopy;
497             sampledImageViewCopy      = createImageView(vk, device, &imageViewCreateInfo, NULL);
498             ;
499         }
500     }
501 
502     // Create output image
503     {
504         vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
505         if (m_parameters.outputImageHostTransition || m_parameters.hostCopyImageToMemory ||
506             m_parameters.hostTransferLayout)
507             usage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
508         if (m_parameters.command == DISPATCH)
509             usage |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
510 
511         const vk::VkImageCreateInfo createInfo = {
512             vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
513             DE_NULL,                                 // const void*                pNext
514             0u,                                      // VkImageCreateFlags        flags
515             vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
516             m_parameters.imageOutputFormat,          // VkFormat                    format
517             imageSize,                               // VkExtent3D                extent
518             m_parameters.mipLevel + 1,               // uint32_t                    mipLevels
519             1u,                                      // uint32_t                    arrayLayers
520             vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
521             vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
522             usage,                                   // VkImageUsageFlags        usage
523             vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
524             0,                                       // uint32_t                    queueFamilyIndexCount
525             DE_NULL,                                 // const uint32_t*            pQueueFamilyIndices
526             vk::VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
527         };
528 
529         outputImage = de::MovePtr<ImageWithMemory>(
530             new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
531 
532         vk::VkImageViewCreateInfo imageViewCreateInfo = {
533             vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
534             DE_NULL,                                      // const void* pNext;
535             (VkImageViewCreateFlags)0u,                   // VkImageViewCreateFlags flags;
536             **outputImage,                                // VkImage image;
537             vk::VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
538             m_parameters.imageOutputFormat,               // VkFormat format;
539             componentMapping,                             // VkComponentMapping components;
540             outputSubresourceRange                        // VkImageSubresourceRange subresourceRange;
541         };
542         outputImageView = createImageView(vk, device, &imageViewCreateInfo, NULL);
543     }
544 
545     const vk::VkAttachmentDescription colorAttachmentDescription = {
546         (vk::VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags    flags
547         m_parameters.imageOutputFormat,       // VkFormat                        format
548         vk::VK_SAMPLE_COUNT_1_BIT,            // VkSampleCountFlagBits           samples
549         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp              loadOp
550         vk::VK_ATTACHMENT_STORE_OP_STORE,     // VkAttachmentStoreOp             storeOp
551         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp              stencilLoadOp
552         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp             stencilStoreOp
553         vk::VK_IMAGE_LAYOUT_GENERAL,          // VkImageLayout                   initialLayout
554         vk::VK_IMAGE_LAYOUT_GENERAL           // VkImageLayout                   finalLayout
555     };
556 
557     const vk::VkAttachmentReference colorAttachmentRef = {
558         0u,                         // uint32_t         attachment
559         vk::VK_IMAGE_LAYOUT_GENERAL // VkImageLayout    layout
560     };
561 
562     const vk::VkSubpassDescription subpassDescription = {
563         (vk::VkSubpassDescriptionFlags)0u,   // VkSubpassDescriptionFlags       flags
564         vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint             pipelineBindPoint
565         0u,                                  // uint32_t                        inputAttachmentCount
566         DE_NULL,                             // const VkAttachmentReference*    pInputAttachments
567         1u,                                  // uint32_t                        colorAttachmentCount
568         &colorAttachmentRef,                 // const VkAttachmentReference*    pColorAttachments
569         DE_NULL,                             // const VkAttachmentReference*    pResolveAttachments
570         DE_NULL,                             // const VkAttachmentReference*    pDepthStencilAttachment
571         0u,                                  // uint32_t                        preserveAttachmentCount
572         DE_NULL                              // const uint32_t*                 pPreserveAttachments
573     };
574 
575     Move<vk::VkRenderPass> renderPass;
576     Move<vk::VkFramebuffer> framebuffer;
577     if (!m_parameters.dynamicRendering && m_parameters.command == DRAW)
578     {
579         const vk::VkRenderPassCreateInfo renderPassInfo = {
580             vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
581             nullptr,                                       // const void* pNext;
582             0u,                                            // VkRenderPassCreateFlags flags;
583             1u,                                            // uint32_t attachmentCount;
584             &colorAttachmentDescription,                   // const VkAttachmentDescription* pAttachments;
585             1u,                                            // uint32_t subpassCount;
586             &subpassDescription,                           // const VkSubpassDescription* pSubpasses;
587             0u,                                            // uint32_t dependencyCount;
588             nullptr,                                       // const VkSubpassDependency* pDependencies;
589         };
590         renderPass  = createRenderPass(vk, device, &renderPassInfo);
591         framebuffer = makeFramebuffer(vk, device, *renderPass, *outputImageView, renderArea.extent.width,
592                                       renderArea.extent.height);
593     }
594 
595     const std::vector<vk::VkViewport> viewports{makeViewport(renderArea.extent)};
596     const std::vector<vk::VkRect2D> scissors{makeRect2D(renderArea.extent)};
597 
598     vk::ShaderWrapper vert = vk::ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"));
599     vk::ShaderWrapper frag = vk::ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"));
600 
601     DescriptorSetLayoutBuilder descriptorBuilder;
602     descriptorBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
603                                        vk::VK_SHADER_STAGE_FRAGMENT_BIT | vk::VK_SHADER_STAGE_COMPUTE_BIT);
604     if (m_parameters.command == DISPATCH)
605         descriptorBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
606 
607     const auto descriptorSetLayout(descriptorBuilder.build(vk, device));
608     const vk::PipelineLayoutWrapper pipelineLayout(PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, vk, device,
609                                                    *descriptorSetLayout);
610 
611     DescriptorPoolBuilder poolBuilder;
612     poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
613     if (m_parameters.command == DISPATCH)
614         poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
615     const Move<vk::VkDescriptorPool> descriptorPool =
616         poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
617     const Move<vk::VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
618 
619     vk::VkSamplerCreateInfo samplerParams = {
620         vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
621         DE_NULL,                                     // const void* pNext;
622         0u,                                          // VkSamplerCreateFlags flags;
623         vk::VK_FILTER_NEAREST,                       // VkFilter magFilter;
624         vk::VK_FILTER_NEAREST,                       // VkFilter minFilter;
625         vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
626         vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeU;
627         vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeV;
628         vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeW;
629         0.0f,                                        // float mipLodBias;
630         VK_FALSE,                                    // VkBool32 anisotropyEnable;
631         0.0f,                                        // float maxAnisotropy;
632         VK_FALSE,                                    // VkBool32 compareEnable;
633         vk::VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
634         0.0f,                                        // float minLod;
635         VK_LOD_CLAMP_NONE,                           // float maxLod;
636         vk::VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,      // VkBorderColor borderColor;
637         VK_FALSE                                     // VkBool32 unnormalizedCoordinates;
638     };
639     const vk::Move<vk::VkSampler> sampler = createSampler(vk, device, &samplerParams);
640     vk::VkDescriptorImageInfo descriptorSrcImageInfo(
641         makeDescriptorImageInfo(*sampler, *sampledImageView, vk::VK_IMAGE_LAYOUT_GENERAL));
642     const vk::VkDescriptorImageInfo descriptorDstImageInfo(
643         makeDescriptorImageInfo(*sampler, *outputImageView, vk::VK_IMAGE_LAYOUT_GENERAL));
644 
645     const vk::VkPipelineVertexInputStateCreateInfo vertexInput = {
646         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
647         nullptr,                                                       // const void* pNext;
648         0u,                                                            // VkPipelineVertexInputStateCreateFlags flags;
649         0u,                                                            // uint32_t vertexBindingDescriptionCount;
650         DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
651         0u,      // uint32_t vertexAttributeDescriptionCount;
652         DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
653     };
654 
655     GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, deviceExtensions,
656                                      vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
657     Move<vk::VkPipeline> computePipeline;
658 
659     if (m_parameters.command == DRAW)
660     {
661         vk::VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo;
662         if (m_parameters.dynamicRendering)
663         {
664             pipelineRenderingCreateInfo = {
665                 vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType    sType
666                 DE_NULL,                                              // const void*        pNext
667                 0u,                                                   // uint32_t            viewMask
668                 1u,                                                   // uint32_t            colorAttachmentCount
669                 &m_parameters.imageOutputFormat,                      // const VkFormat*    pColorAttachmentFormats
670                 vk::VK_FORMAT_UNDEFINED,                              // VkFormat            depthAttachmentFormat
671                 vk::VK_FORMAT_UNDEFINED                               // VkFormat            stencilAttachmentFormat
672             };
673         }
674 
675         vk::PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
676         renderingCreateInfoWrapper.ptr = m_parameters.dynamicRendering ? &pipelineRenderingCreateInfo : DE_NULL;
677 
678         pipeline.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
679             .setDefaultRasterizationState()
680             .setDefaultMultisampleState()
681             .setDefaultDepthStencilState()
682             .setDefaultColorBlendState()
683             .setupVertexInputState(&vertexInput)
684             .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vert, DE_NULL, {},
685                                               {}, {}, DE_NULL, DE_NULL, renderingCreateInfoWrapper)
686             .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, frag)
687             .setupFragmentOutputState(*renderPass)
688             .setMonolithicPipelineLayout(pipelineLayout)
689             .buildPipeline();
690     }
691     else
692     {
693         const Unique<vk::VkShaderModule> cs(
694             vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
695         const vk::VkPipelineShaderStageCreateInfo pipelineShaderStageParams = {
696             vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
697             DE_NULL,                                                 // pNext
698             (VkPipelineShaderStageCreateFlags)0u,                    // flags
699             vk::VK_SHADER_STAGE_COMPUTE_BIT,                         // stage
700             *cs,                                                     // module
701             "main",                                                  // pName
702             DE_NULL,                                                 // pSpecializationInfo
703         };
704         const vk::VkComputePipelineCreateInfo pipelineCreateInfo = {
705             vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
706             DE_NULL,                                            // pNext
707             (VkPipelineCreateFlags)0u,                          // flags
708             pipelineShaderStageParams,                          // stage
709             *pipelineLayout,                                    // layout
710             DE_NULL,                                            // basePipelineHandle
711             0,                                                  // basePipelineIndex
712         };
713         computePipeline = createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo);
714     }
715 
716     de::MovePtr<BufferWithMemory> colorOutputBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
717         vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
718         MemoryRequirement::HostVisible));
719 
720     // Load sampled image
721     if (m_parameters.hostCopyMemoryToImage)
722     {
723         transitionImageLayout(&cmdBuffer, sampledImage, vk::VK_IMAGE_LAYOUT_UNDEFINED, m_parameters.dstLayout,
724                               sampledSubresourceRange);
725         commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage << " to layout "
726                     << getImageLayoutStr(m_parameters.dstLayout).toString() << "\n";
727 
728         copyMemoryToImage(testData, sampledImage, sampledChannelSize * sampledNumChannels, sampledSubresourceLayers, 0,
729                           0, mipImageSize.width, mipImageSize.height);
730         commandsLog << "vkCopyMemoryToImageEXT() with image " << sampledImage << ", xOffset (0), yOffset (0), width ("
731                     << mipImageSize.width << "), height (" << mipImageSize.height << ")\n";
732 
733         de::Random randomGen(deInt32Hash((uint32_t)m_parameters.imageSampledFormat) ^
734                              deInt32Hash((uint32_t)mipImageSize.width) ^ deInt32Hash((uint32_t)mipImageSize.height) ^
735                              deInt32Hash((uint32_t)mipImageSize.depth));
736         for (int i = 0; i < 20; ++i)
737         {
738             int32_t xOffset = randomGen.getInt32() % (mipImageSize.width / 2);
739             int32_t yOffset = randomGen.getInt32() % (mipImageSize.height / 2);
740             uint32_t width  = deMaxu32(randomGen.getUint32() % (mipImageSize.width / 2), 1u);
741             uint32_t height = deMaxu32(randomGen.getUint32() % (mipImageSize.height / 2), 1u);
742 
743             if (isCompressedFormat(m_parameters.imageSampledFormat))
744             {
745                 uint32_t blockWidth  = getBlockWidth(m_parameters.imageSampledFormat);
746                 uint32_t blockHeight = getBlockHeight(m_parameters.imageSampledFormat);
747                 xOffset              = (xOffset / blockWidth) * blockWidth;
748                 yOffset              = (yOffset / blockHeight) * blockHeight;
749                 width                = deMaxu32((width / blockWidth) * blockWidth, blockWidth);
750                 height               = deMaxu32((height / blockHeight) * blockHeight, blockHeight);
751             }
752 
753             copyMemoryToImage(testData, sampledImage, sampledChannelSize * sampledNumChannels, sampledSubresourceLayers,
754                               xOffset, yOffset, width, height);
755             commandsLog << "vkCopyMemoryToImageEXT() with image " << sampledImage << ", xOffset (" << xOffset
756                         << "), yOffset (" << yOffset << "), width (" << width << "), height (" << height << ")\n";
757         }
758 
759         if (m_parameters.dstLayout != vk::VK_IMAGE_LAYOUT_GENERAL)
760         {
761             transitionImageLayout(&cmdBuffer, sampledImage, m_parameters.dstLayout, vk::VK_IMAGE_LAYOUT_GENERAL,
762                                   sampledSubresourceRange);
763             commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage
764                         << " to layout VK_IMAGE_LAYOUT_GENERAL\n";
765         }
766     }
767     else
768     {
769         de::MovePtr<BufferWithMemory> sampledBuffer = de::MovePtr<BufferWithMemory>(
770             new BufferWithMemory(vk, device, alloc,
771                                  makeBufferCreateInfo(sampledBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
772                                                                              vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
773                                  MemoryRequirement::HostVisible));
774 
775         auto &bufferAlloc = sampledBuffer->getAllocation();
776         memcpy(bufferAlloc.getHostPtr(), testData.data(), sampledBufferSize);
777         flushAlloc(vk, device, bufferAlloc);
778 
779         transitionImageLayout(&cmdBuffer, sampledImage, vk::VK_IMAGE_LAYOUT_UNDEFINED, m_parameters.dstLayout,
780                               sampledSubresourceRange);
781         commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage << " to layout"
782                     << getImageLayoutStr(m_parameters.dstLayout).toString() << "\n";
783 
784         vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
785         const vk::VkBufferImageCopy copyRegion = {
786             0,
787             0,
788             0,
789             sampledSubresourceLayers,
790             imageOffset,
791             {
792                 mipImageSize.width,
793                 mipImageSize.height,
794                 mipImageSize.depth,
795             },
796         };
797         vk.cmdCopyBufferToImage(*cmdBuffer, sampledBuffer->get(), sampledImage, m_parameters.dstLayout, 1u,
798                                 &copyRegion);
799         commandsLog << "vkCmdCopyBufferToImage() with image " << sampledImage << ", xOffset ("
800                     << copyRegion.imageOffset.x << "), yOffset (" << copyRegion.imageOffset.y << "), width ("
801                     << mipImageSize.width << "), height (" << mipImageSize.height << ")\n";
802 
803         {
804             auto imageMemoryBarrier = makeImageMemoryBarrier(
805                 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, m_parameters.dstLayout,
806                 m_parameters.intermediateLayout, sampledImage, sampledSubresourceRange);
807             vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
808                                   0u, 0u, DE_NULL, 0u, DE_NULL, 1, &imageMemoryBarrier);
809         }
810 
811         vk::endCommandBuffer(vk, *cmdBuffer);
812         uint32_t semaphoreCount         = 0;
813         vk::VkSemaphore semaphore       = DE_NULL;
814         VkPipelineStageFlags waitStages = 0;
815         if (m_parameters.sparse)
816         {
817             semaphoreCount = 1;
818             semaphore      = sparseSampledImage->getSemaphore();
819             waitStages     = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
820         }
821         vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer, false, 1u, semaphoreCount, &semaphore, &waitStages);
822 
823         if (m_parameters.intermediateLayout != vk::VK_IMAGE_LAYOUT_GENERAL)
824         {
825             transitionImageLayout(&cmdBuffer, sampledImage, m_parameters.intermediateLayout,
826                                   vk::VK_IMAGE_LAYOUT_GENERAL, sampledSubresourceRange);
827             commandsLog << "vkTransitionImageLayoutEXT() image " << sampledImage
828                         << " to layout VK_IMAGE_LAYOUT_GENERAL\n";
829         }
830     }
831 
832     if (m_parameters.memcpyFlag)
833     {
834         vk::VkImageSubresource2EXT subresource2 = {
835             vk::VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT, // VkStructureType sType;
836             DE_NULL,                                       // void* pNext;
837             sampledSubresource                             // VkImageSubresource imageSubresource;
838         };
839 
840         vk::VkSubresourceHostMemcpySizeEXT subresourceHostMemcpySize = vk::initVulkanStructure();
841         vk::VkSubresourceLayout2EXT subresourceLayout = vk::initVulkanStructure(&subresourceHostMemcpySize);
842         vk.getImageSubresourceLayout2KHR(device, sampledImage, &subresource2, &subresourceLayout);
843 
844         std::vector<uint8_t> data((size_t)subresourceHostMemcpySize.size);
845 
846         const vk::VkImageToMemoryCopyEXT region = {
847             vk::VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT, // VkStructureType sType;
848             DE_NULL,                                        // const void* pNext;
849             data.data(),                                    // void* memoryHostPointer;
850             0u,                                             // uint32_t memoryRowLength;
851             0u,                                             // uint32_t memoryImageHeight;
852             sampledSubresourceLayers,                       // VkImageSubresourceLayers imageSubresource;
853             imageOffset,                                    // VkOffset3D imageOffset;
854             mipImageSize,                                   // VkExtent3D imageExtent;
855         };
856 
857         const vk::VkCopyImageToMemoryInfoEXT copyImageToMemoryInfo = {
858             vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT, // VkStructureType sType;
859             DE_NULL,                                             // const void* pNext;
860             vk::VK_HOST_IMAGE_COPY_MEMCPY_EXT,                   // VkMemoryImageCopyFlagsEXT flags;
861             sampledImage,                                        // VkImage srcImage;
862             vk::VK_IMAGE_LAYOUT_GENERAL,                         // VkImageLayout srcImageLayout;
863             1,                                                   // uint32_t regionCount;
864             &region,                                             // const VkImageToMemoryCopyEXT* pRegions;
865         };
866         vk.copyImageToMemoryEXT(device, &copyImageToMemoryInfo);
867         commandsLog << "vkCopyImageToMemoryEXT() with image " << sampledImage << ", xOffset (" << region.imageOffset.x
868                     << "), yOffset (" << region.imageOffset.y << "), width (" << mipImageSize.width << "), height ("
869                     << mipImageSize.height << ")\n";
870 
871         transitionImageLayout(&cmdBuffer, sampledImageCopy, vk::VK_IMAGE_LAYOUT_UNDEFINED, m_parameters.dstLayout,
872                               sampledSubresourceRange);
873 
874         const vk::VkMemoryToImageCopyEXT toImageRegion = {
875             vk::VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT, // VkStructureType sType;
876             DE_NULL,                                        // const void* pNext;
877             data.data(),                                    // const void* memoryHostPointer;
878             0,                                              // uint32_t memoryRowLength;
879             0,                                              // uint32_t memoryImageHeight;
880             sampledSubresourceLayers,                       // VkImageSubresourceLayers imageSubresource;
881             imageOffset,                                    // VkOffset3D imageOffset;
882             mipImageSize                                    // VkExtent3D imageExtent;
883         };
884 
885         vk::VkCopyMemoryToImageInfoEXT copyMemoryToImageInfo = {
886             vk::VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT, // VkStructureType sType;
887             DE_NULL,                                             // const void* pNext;
888             vk::VK_HOST_IMAGE_COPY_MEMCPY_EXT,                   // VkMemoryImageCopyFlagsEXT flags;
889             sampledImageCopy,                                    // VkImage dstImage;
890             m_parameters.dstLayout,                              // VkImageLayout dstImageLayout;
891             1u,                                                  // uint32_t regionCount;
892             &toImageRegion,                                      // const VkMemoryToImageCopyEXT* pRegions;
893         };
894         vk.copyMemoryToImageEXT(device, &copyMemoryToImageInfo);
895         commandsLog << "vkCopyMemoryToImageEXT() with image " << sampledImageCopy << ", xOffset ("
896                     << toImageRegion.imageOffset.x << "), yOffset (" << toImageRegion.imageOffset.y << "), width ("
897                     << toImageRegion.imageExtent.width << "), height (" << toImageRegion.imageExtent.height << ")\n";
898         descriptorSrcImageInfo.imageView = *sampledImageViewCopy;
899 
900         transitionImageLayout(&cmdBuffer, sampledImageCopy, m_parameters.dstLayout, vk::VK_IMAGE_LAYOUT_GENERAL,
901                               sampledSubresourceRange);
902     }
903 
904     // Transition output image
905     transitionImageLayout(&cmdBuffer, **outputImage, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL,
906                           outputSubresourceRange);
907     commandsLog << "vkTransitionImageLayoutEXT() image " << **outputImage << " to layout VK_IMAGE_LAYOUT_GENERAL\n";
908     vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
909 
910     vk::DescriptorSetUpdateBuilder updateBuilder;
911     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
912                               vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorSrcImageInfo);
913     if (m_parameters.command == DISPATCH)
914         updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
915                                   vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo);
916     updateBuilder.update(vk, device);
917 
918     if (m_parameters.command == DRAW)
919     {
920         if (m_parameters.dynamicRendering)
921             beginRendering(vk, *cmdBuffer, *outputImageView, renderArea, vk::VkClearValue(),
922                            vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE);
923         else
924             beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea);
925 
926         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
927         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1,
928                                  &*descriptorSet, 0, DE_NULL);
929         vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
930         commandsLog << "vkCmdDraw()\n";
931 
932         if (m_parameters.dynamicRendering)
933             endRendering(vk, *cmdBuffer);
934         else
935             endRenderPass(vk, *cmdBuffer);
936 
937         const auto postImageBarrier = makeImageMemoryBarrier(
938             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL,
939             m_parameters.srcLayout, **outputImage, outputSubresourceRange);
940         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
941                               vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0,
942                               (const vk::VkMemoryBarrier *)DE_NULL, 0, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1,
943                               &postImageBarrier);
944     }
945     else
946     {
947         const auto imageMemoryBarrier =
948             makeImageMemoryBarrier(0u, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
949                                    vk::VK_IMAGE_LAYOUT_GENERAL, **outputImage, outputSubresourceRange);
950         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
951                               vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0u, DE_NULL, 0u, DE_NULL, 1u,
952                               &imageMemoryBarrier);
953         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
954         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, 1, &*descriptorSet,
955                                  0, DE_NULL);
956         vk.cmdDispatch(*cmdBuffer, renderArea.extent.width, renderArea.extent.height, 1);
957         commandsLog << "vkCmdDispatch()\n";
958 
959         vk::VkImageMemoryBarrier postImageBarrier = {
960             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
961             DE_NULL,                                    // const void*                pNext
962             vk::VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlags            srcAccessMask
963             vk::VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags            dstAccessMask
964             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout            oldLayout
965             m_parameters.srcLayout,                     // VkImageLayout            newLayout
966             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                    srcQueueFamilyIndex
967             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                    dstQueueFamilyIndex
968             **outputImage,                              // VkImage                    image
969             outputSubresourceRange                      // VkImageSubresourceRange    subresourceRange
970         };
971 
972         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
973                               (VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
974                               (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &postImageBarrier);
975     }
976 
977     const vk::VkBufferImageCopy copyRegion = {
978         0u,                                                    // VkDeviceSize bufferOffset;
979         0u,                                                    // uint32_t bufferRowLength;
980         0u,                                                    // uint32_t bufferImageHeight;
981         outputSubresourceLayers,                               // VkImageSubresourceLayers imageSubresource;
982         imageOffset,                                           // VkOffset3D imageOffset;
983         {renderArea.extent.width, renderArea.extent.height, 1} // VkExtent3D imageExtent;
984     };
985     vk.cmdCopyImageToBuffer(*cmdBuffer, **outputImage, m_parameters.srcLayout, **colorOutputBuffer, 1u, &copyRegion);
986     commandsLog << "vkCmdCopyImageToBuffer() with image " << **outputImage << ", xOffset (" << imageOffset.x
987                 << "), yOffset (" << imageOffset.y << "), width (" << renderArea.extent.width << "), height ("
988                 << renderArea.extent.height << "\n";
989     vk::endCommandBuffer(vk, *cmdBuffer);
990 
991     vk::submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
992 
993     // Verify image
994     tcu::ConstPixelBufferAccess resultBuffer =
995         tcu::ConstPixelBufferAccess(outputFormat, renderArea.extent.width, renderArea.extent.height, 1,
996                                     (const void *)colorOutputBuffer->getAllocation().getHostPtr());
997 
998     if (m_parameters.hostCopyImageToMemory)
999     {
1000         const uint32_t paddedBufferSize = (mipImageSize.width + m_parameters.padding) *
1001                                           (mipImageSize.height + m_parameters.padding) * outputNumChannels *
1002                                           outputChannelSize;
1003         const uint32_t memoryRowLength   = (mipImageSize.width + m_parameters.padding);
1004         const uint32_t memoryImageHeight = (mipImageSize.height + m_parameters.padding);
1005         std::vector<uint8_t> paddedData(paddedBufferSize);
1006         std::vector<uint8_t> data(outputBufferSize);
1007 
1008         std::vector<vk::VkImageToMemoryCopyEXT> regions(m_parameters.regionsCount);
1009 
1010         for (uint32_t i = 0; i < m_parameters.regionsCount; ++i)
1011         {
1012             vk::VkOffset3D offset = {0, (int32_t)(mipImageSize.height / m_parameters.regionsCount * i), 0};
1013             vk::VkExtent3D extent = {mipImageSize.width, mipImageSize.height / m_parameters.regionsCount, 1};
1014             if (i == m_parameters.regionsCount - 1)
1015                 extent.height = mipImageSize.height - mipImageSize.height / m_parameters.regionsCount * i;
1016 
1017             uint32_t dataOffset =
1018                 (mipImageSize.width + m_parameters.padding) * offset.y * outputNumChannels * outputChannelSize;
1019 
1020             const vk::VkImageToMemoryCopyEXT region = {
1021                 vk::VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT, // VkStructureType sType;
1022                 DE_NULL,                                        // const void* pNext;
1023                 &paddedData[dataOffset],                        // void* memoryHostPointer;
1024                 memoryRowLength,                                // uint32_t memoryRowLength;
1025                 memoryImageHeight,                              // uint32_t memoryImageHeight;
1026                 outputSubresourceLayers,                        // VkImageSubresourceLayers imageSubresource;
1027                 offset,                                         // VkOffset3D imageOffset;
1028                 extent,                                         // VkExtent3D imageExtent;
1029             };
1030 
1031             regions[i] = region;
1032         }
1033 
1034         const vk::VkCopyImageToMemoryInfoEXT copyImageToMemoryInfo = {
1035             vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT, // VkStructureType sType;
1036             DE_NULL,                                             // const void* pNext;
1037             0u,                                                  // VkMemoryImageCopyFlagsEXT flags;
1038             **outputImage,                                       // VkImage srcImage;
1039             m_parameters.srcLayout,                              // VkImageLayout srcImageLayout;
1040             (uint32_t)regions.size(),                            // uint32_t regionCount;
1041             regions.data(),                                      // const VkImageToMemoryCopyEXT* pRegions;
1042         };
1043         vk.copyImageToMemoryEXT(device, &copyImageToMemoryInfo);
1044         commandsLog << "vkCopyImageToMemoryEXT() with image " << **outputImage << "\n";
1045 
1046         for (uint32_t j = 0; j < mipImageSize.height; ++j)
1047         {
1048             for (uint32_t i = 0; i < mipImageSize.width; ++i)
1049             {
1050                 for (uint32_t k = 0; k < outputNumChannels * outputChannelSize; ++k)
1051                 {
1052                     uint32_t dstIndex = j * mipImageSize.width * (outputNumChannels * outputChannelSize) +
1053                                         i * (outputNumChannels * outputChannelSize) + k;
1054                     uint32_t srcIndex =
1055                         j * (mipImageSize.width + m_parameters.padding) * (outputNumChannels * outputChannelSize) +
1056                         i * (outputNumChannels * outputChannelSize) + k;
1057                     data[dstIndex] = paddedData[srcIndex];
1058                 }
1059             }
1060         }
1061 
1062         bool match = true;
1063         if (m_parameters.imageOutputFormat == VK_FORMAT_R10X6_UNORM_PACK16)
1064         {
1065             for (uint32_t i = 0; i < outputBufferSize / 2; ++i)
1066             {
1067                 uint16_t ref    = ((uint16_t *)data.data())[i];
1068                 uint16_t result = ((uint16_t *)resultBuffer.getDataPtr())[i];
1069                 if ((ref & 0xffc0) != (result & 0xffc0))
1070                     match = false;
1071             }
1072         }
1073         else
1074         {
1075             match = memcmp(data.data(), resultBuffer.getDataPtr(), outputBufferSize) == 0;
1076         }
1077         if (!match)
1078         {
1079             log << tcu::TestLog::Message << commandsLog.str() << tcu::TestLog::EndMessage;
1080             for (uint32_t i = 0; i < outputBufferSize; ++i)
1081             {
1082                 if (data[i] != ((uint8_t *)resultBuffer.getDataPtr())[i])
1083                 {
1084                     log << tcu::TestLog::Message << "At byte " << i << " data from vkCopyImageToMemoryEXT() is "
1085                         << data[i] << ", but data from vkCmdCopyImageToBuffer() (after padding) is "
1086                         << ((uint8_t *)resultBuffer.getDataPtr())[i] << tcu::TestLog::EndMessage;
1087                     break;
1088                 }
1089             }
1090             return tcu::TestStatus::fail("copyImageToMemoryEXT failed");
1091         }
1092     }
1093 
1094     if (m_parameters.imageOutputFormat == m_parameters.imageSampledFormat)
1095     {
1096         std::vector<uint8_t> resultData(sampledBufferSize);
1097         const Allocation &outputAlloc = colorOutputBuffer->getAllocation();
1098         deMemcpy(resultData.data(), outputAlloc.getHostPtr(), sampledBufferSize);
1099 
1100         bool match = true;
1101         if (m_parameters.imageOutputFormat == VK_FORMAT_R10X6_UNORM_PACK16)
1102         {
1103             for (uint32_t i = 0; i < sampledBufferSize / 2; ++i)
1104             {
1105                 uint16_t ref    = ((uint16_t *)testData.data())[i];
1106                 uint16_t result = ((uint16_t *)resultData.data())[i];
1107                 if ((ref & 0xffc0) != (result & 0xffc0))
1108                 {
1109                     match = false;
1110                     break;
1111                 }
1112             }
1113         }
1114         else
1115         {
1116             for (uint32_t i = 0; i < sampledBufferSize; ++i)
1117             {
1118                 if (resultData[i] != testData[i])
1119                 {
1120                     match = false;
1121                     break;
1122                 }
1123             }
1124         }
1125         if (!match)
1126         {
1127             if (!isCompressedFormat(m_parameters.imageSampledFormat))
1128             {
1129                 const tcu::ConstPixelBufferAccess bufferData(
1130                     mapVkFormat(m_parameters.imageSampledFormat), m_parameters.imageSize.width,
1131                     m_parameters.imageSize.height, m_parameters.imageSize.depth, outputAlloc.getHostPtr());
1132 
1133                 m_context.getTestContext().getLog()
1134                     << tcu::TestLog::Section("host_copy_result", "host_copy_result")
1135                     << tcu::LogImage("image", "", bufferData) << tcu::TestLog::EndSection;
1136             }
1137             return tcu::TestStatus::fail("Image verification failed");
1138         }
1139     }
1140     return tcu::TestStatus::pass("Pass");
1141 }
1142 
1143 class HostImageCopyTestCase : public vkt::TestCase
1144 {
1145 public:
HostImageCopyTestCase(tcu::TestContext & context,const char * name,const TestParameters & parameters)1146     HostImageCopyTestCase(tcu::TestContext &context, const char *name, const TestParameters &parameters)
1147         : TestCase(context, name)
1148         , m_parameters(parameters)
1149     {
1150     }
1151 
1152 private:
1153     void checkSupport(vkt::Context &context) const;
1154     void initPrograms(vk::SourceCollections &programCollection) const;
createInstance(vkt::Context & context) const1155     vkt::TestInstance *createInstance(vkt::Context &context) const
1156     {
1157         return new HostImageCopyTestInstance(context, m_parameters);
1158     }
1159 
1160     const TestParameters m_parameters;
1161 };
1162 
checkSupport(vkt::Context & context) const1163 void HostImageCopyTestCase::checkSupport(vkt::Context &context) const
1164 {
1165     vk::VkInstance instance(context.getInstance());
1166     vk::InstanceDriver instanceDriver(context.getPlatformInterface(), instance);
1167     const vk::InstanceInterface &vki    = context.getInstanceInterface();
1168     vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1169 
1170     context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1171 
1172     if (m_parameters.dynamicRendering)
1173         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1174 
1175     if (m_parameters.sparse)
1176         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
1177 
1178     vk::VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeatures = {
1179         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT, // VkStructureType                    sType
1180         DE_NULL,                                                            // const void*                        pNext
1181         VK_FALSE,                                                           // VkBool32 hostImageCopy;
1182     };
1183 
1184     vk::VkPhysicalDeviceFeatures features;
1185     deMemset(&features, 0, sizeof(vk::VkPhysicalDeviceFeatures));
1186     vk::VkPhysicalDeviceFeatures2 features2 = {
1187         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType                    sType
1188         &hostImageCopyFeatures,                           // const void*                        pNext
1189         features                                          // VkPhysicalDeviceFeatures            features
1190     };
1191 
1192     instanceDriver.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1193 
1194     vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties = {
1195         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT, // VkStructureType sType;
1196         DE_NULL,                                                              // void* pNext;
1197         0u,                                                                   // uint32_t copySrcLayoutCount;
1198         DE_NULL,                                                              // VkImageLayout* pCopySrcLayouts;
1199         0u,                                                                   // uint32_t copyDstLayoutCount;
1200         DE_NULL,                                                              // VkImageLayout* pCopyDstLayouts;
1201         {},   // uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE];
1202         false // VkBool32 identicalMemoryTypeRequirements;
1203     };
1204     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1205     std::vector<vk::VkImageLayout> srcLayouts(hostImageCopyProperties.copySrcLayoutCount);
1206     std::vector<vk::VkImageLayout> dstLayouts(hostImageCopyProperties.copyDstLayoutCount);
1207     hostImageCopyProperties.pCopySrcLayouts = srcLayouts.data();
1208     hostImageCopyProperties.pCopyDstLayouts = dstLayouts.data();
1209     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1210     bool layoutSupported             = false;
1211     bool intermediateLayoutSupported = false;
1212     for (uint32_t i = 0; i < hostImageCopyProperties.copySrcLayoutCount; ++i)
1213     {
1214         if (hostImageCopyProperties.pCopySrcLayouts[i] == m_parameters.srcLayout)
1215             layoutSupported = true;
1216         if (hostImageCopyProperties.pCopySrcLayouts[i] == m_parameters.intermediateLayout)
1217             intermediateLayoutSupported = true;
1218     }
1219     if (layoutSupported == false || intermediateLayoutSupported == false)
1220         TCU_THROW(NotSupportedError, "Layout not supported for src host copy");
1221     layoutSupported = false;
1222     for (uint32_t i = 0; i < hostImageCopyProperties.copyDstLayoutCount; ++i)
1223     {
1224         if (hostImageCopyProperties.pCopyDstLayouts[i] == m_parameters.dstLayout)
1225         {
1226             layoutSupported = true;
1227             break;
1228         }
1229     }
1230     if (layoutSupported == false)
1231         TCU_THROW(NotSupportedError, "Layout not supported for dst host copy");
1232 
1233     vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_SAMPLED_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1234     if (m_parameters.hostCopyMemoryToImage || m_parameters.hostCopyImageToMemory || m_parameters.memcpyFlag ||
1235         m_parameters.hostTransferLayout)
1236         usage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
1237     if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
1238         usage |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1239     else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
1240         usage |= vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1241     else if (m_parameters.intermediateLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
1242         usage |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1243 
1244     vk::VkImageCreateFlags flags = 0u;
1245     if (m_parameters.sparse)
1246         flags |= vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT | vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT;
1247     vk::VkImageFormatProperties imageFormatProperties;
1248     if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.imageSampledFormat,
1249                                                    vk::VK_IMAGE_TYPE_2D, m_parameters.sampledTiling, usage, flags,
1250                                                    &imageFormatProperties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1251         TCU_THROW(NotSupportedError, "Image format not supported.");
1252 
1253     vk::VkImageUsageFlags outputUsage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1254     if (m_parameters.outputImageHostTransition || m_parameters.hostCopyImageToMemory)
1255         outputUsage |= vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
1256     if (m_parameters.command == DISPATCH)
1257         outputUsage |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
1258     vk::VkImageFormatProperties outputImageFormatProperties;
1259     if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.imageOutputFormat, vk::VK_IMAGE_TYPE_2D,
1260                                                    vk::VK_IMAGE_TILING_OPTIMAL, outputUsage, flags,
1261                                                    &outputImageFormatProperties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1262         TCU_THROW(NotSupportedError, "Image format not supported.");
1263 
1264     vk::VkFormatProperties3 formatProperties3 = vk::initVulkanStructure();
1265     vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
1266     vki.getPhysicalDeviceFormatProperties2(context.getPhysicalDevice(), m_parameters.imageSampledFormat,
1267                                            &formatProperties2);
1268     if (m_parameters.sampledTiling == vk::VK_IMAGE_TILING_LINEAR &&
1269         (formatProperties3.linearTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1270         TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for linear tiling.");
1271     if (m_parameters.sampledTiling == vk::VK_IMAGE_TILING_OPTIMAL &&
1272         (formatProperties3.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1273         TCU_THROW(NotSupportedError, "Format feature host image transfer not supported for optimal tiling.");
1274 
1275     if (hostImageCopyFeatures.hostImageCopy != VK_TRUE)
1276         TCU_THROW(NotSupportedError, "hostImageCopy not supported");
1277     if (imageFormatProperties.maxMipLevels <= m_parameters.mipLevel)
1278         TCU_THROW(NotSupportedError, "Required image mip levels not supported.");
1279 
1280     if (m_parameters.command == DISPATCH)
1281         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
1282 }
1283 
initPrograms(vk::SourceCollections & programCollection) const1284 void HostImageCopyTestCase::initPrograms(vk::SourceCollections &programCollection) const
1285 {
1286     {
1287         std::ostringstream vert;
1288         vert << "#version 450\n"
1289              << "layout (location=0) out vec2 texCoord;\n"
1290              << "void main()\n"
1291              << "{\n"
1292              << "    texCoord = vec2(gl_VertexIndex & 1u, (gl_VertexIndex >> 1u) & 1u);"
1293              << "    gl_Position = vec4(texCoord * 2.0f - 1.0f, 0.0f, 1.0f);\n"
1294              << "}\n";
1295 
1296         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
1297     }
1298     {
1299         std::string output;
1300         if (isDepthStencilFormat(m_parameters.imageSampledFormat))
1301             output = "    out_color = vec4(texture(combinedSampler, texCoord).r, 0, 0, 0);\n";
1302         else
1303             output = "    out_color = texture(combinedSampler, texCoord);\n";
1304 
1305         std::ostringstream frag;
1306         frag << "#version 450\n"
1307              << "layout (location=0) out vec4 out_color;\n"
1308              << "layout (location=0) in vec2 texCoord;\n"
1309              << "layout (set=0, binding=0) uniform sampler2D combinedSampler;\n"
1310              << "void main()\n"
1311              << "{\n"
1312              << output << "}\n";
1313 
1314         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
1315     }
1316     {
1317         std::string image;
1318         std::string output;
1319         if (m_parameters.imageOutputFormat == vk::VK_FORMAT_R8G8B8A8_UINT)
1320         {
1321             image  = "uimage2D";
1322             output = "uvec4(texture(combinedSampler, vec2(pixelCoord) / (textureSize(combinedSampler, 0) - "
1323                      "vec2(0.001f))) * 255)";
1324         }
1325         else
1326         {
1327             image  = "image2D";
1328             output = "texture(combinedSampler, vec2(pixelCoord) / (textureSize(combinedSampler, 0) - vec2(0.001f)))";
1329         }
1330 
1331         std::ostringstream comp;
1332         comp << "#version 450\n"
1333              << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
1334              << "layout (set=0, binding=0) uniform sampler2D combinedSampler;\n"
1335              << "layout (set=0, binding=1) uniform writeonly " << image << " outImage;\n"
1336              << "void main()\n"
1337              << "{\n"
1338              << "    ivec2 pixelCoord = ivec2(gl_GlobalInvocationID.xy);\n"
1339              << "    imageStore(outImage, pixelCoord, " << output << ");\n"
1340              << "}\n";
1341 
1342         programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
1343     }
1344 }
1345 
1346 class PreinitializedTestInstance : public vkt::TestInstance
1347 {
1348 public:
PreinitializedTestInstance(vkt::Context & context,const vk::VkFormat format,vk::VkImageLayout srcLayout,vk::VkImageLayout dstLayout,vk::VkExtent3D size,uint32_t arrayLayers,bool imageToImageCopy,bool memcpy,vk::VkImageTiling tiling,uint32_t offset)1349     PreinitializedTestInstance(vkt::Context &context, const vk::VkFormat format, vk::VkImageLayout srcLayout,
1350                                vk::VkImageLayout dstLayout, vk::VkExtent3D size, uint32_t arrayLayers,
1351                                bool imageToImageCopy, bool memcpy, vk::VkImageTiling tiling, uint32_t offset)
1352         : vkt::TestInstance(context)
1353         , m_format(format)
1354         , m_srcLayout(srcLayout)
1355         , m_dstLayout(dstLayout)
1356         , m_size(size)
1357         , m_arrayLayers(arrayLayers)
1358         , m_imageToImageCopy(imageToImageCopy)
1359         , m_memcpy(memcpy)
1360         , m_tiling(tiling)
1361         , m_offset(offset)
1362     {
1363     }
1364 
1365 private:
1366     tcu::TestStatus iterate(void);
1367 
1368     const vk::VkFormat m_format;
1369     const vk::VkImageLayout m_srcLayout;
1370     const vk::VkImageLayout m_dstLayout;
1371     const vk::VkExtent3D m_size;
1372     const uint32_t m_arrayLayers;
1373     const bool m_imageToImageCopy;
1374     const bool m_memcpy;
1375     const vk::VkImageTiling m_tiling;
1376     const uint32_t m_offset;
1377 };
1378 
iterate(void)1379 tcu::TestStatus PreinitializedTestInstance::iterate(void)
1380 {
1381     vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), m_context.getInstance());
1382     vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1383     const DeviceInterface &vk           = m_context.getDeviceInterface();
1384     const vk::VkDevice device           = m_context.getDevice();
1385     const uint32_t queueFamilyIndex     = m_context.getUniversalQueueFamilyIndex();
1386     const vk::VkQueue queue             = m_context.getUniversalQueue();
1387     auto &alloc                         = m_context.getDefaultAllocator();
1388     tcu::TestLog &log                   = m_context.getTestContext().getLog();
1389 
1390     const auto subresourceRange  = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_arrayLayers);
1391     const auto subresourceLayers = makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_arrayLayers);
1392     const vk::VkOffset3D offset  = {0u, 0u, 0u};
1393 
1394     const auto channelSize = getChannelSize(m_format);
1395     const auto numChannels = getNumChannels(m_format);
1396     const auto bufferCount = m_size.width * m_size.height * m_size.depth * m_arrayLayers * numChannels;
1397     const auto bufferSize  = bufferCount * channelSize;
1398 
1399     const vk::VkCommandPoolCreateInfo cmdPoolInfo = {
1400         vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // sType
1401         DE_NULL,                                             // pNext
1402         vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
1403         queueFamilyIndex,                                    // queuefamilyindex
1404     };
1405     const Move<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolInfo));
1406     const Move<vk::VkCommandBuffer> cmdBuffer(
1407         allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1408 
1409     const vk::SimpleAllocator::OptionalOffsetParams offsetParams(
1410         {m_context.getDeviceProperties().limits.nonCoherentAtomSize, m_offset});
1411     de::MovePtr<Allocator> allocatorWithOffset = de::MovePtr<Allocator>(new SimpleAllocator(
1412         vk, device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()),
1413         offsetParams));
1414 
1415     const vk::VkImageType imageType = m_size.depth > 1 ? vk::VK_IMAGE_TYPE_3D : vk::VK_IMAGE_TYPE_2D;
1416 
1417     uint64_t modifier = 0;
1418     checkSupportedFormatFeatures(instanceDriver, physicalDevice, m_format, m_tiling, &modifier);
1419 
1420     vk::VkImageDrmFormatModifierListCreateInfoEXT drmCreateInfo = vk::initVulkanStructure();
1421     drmCreateInfo.drmFormatModifierCount                        = 1;
1422     drmCreateInfo.pDrmFormatModifiers                           = &modifier;
1423 
1424     vk::VkImageCreateInfo createInfo = {
1425         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
1426         m_tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ? &drmCreateInfo : DE_NULL,
1427         // const void*                pNext
1428         0u,                        // VkImageCreateFlags        flags
1429         imageType,                 // VkImageType                imageType
1430         m_format,                  // VkFormat                    format
1431         m_size,                    // VkExtent3D                extent
1432         1u,                        // uint32_t                    mipLevels
1433         m_arrayLayers,             // uint32_t                    arrayLayers
1434         vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits    samples
1435         m_tiling,                  // VkImageTiling            tiling
1436         vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1437         // VkImageUsageFlags        usage
1438         vk::VK_SHARING_MODE_EXCLUSIVE,     // VkSharingMode            sharingMode
1439         0,                                 // uint32_t                    queueFamilyIndexCount
1440         DE_NULL,                           // const uint32_t*            pQueueFamilyIndices
1441         vk::VK_IMAGE_LAYOUT_PREINITIALIZED // VkImageLayout            initialLayout
1442     };
1443 
1444     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
1445         createInfo.usage |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1446     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
1447         createInfo.usage |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;
1448     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
1449         createInfo.usage |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1450 
1451     de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(
1452         new ImageWithMemory(vk, device, *allocatorWithOffset, createInfo, vk::MemoryRequirement::HostVisible));
1453     de::MovePtr<ImageWithMemory> copyImage = de::MovePtr<ImageWithMemory>(
1454         new ImageWithMemory(vk, device, *allocatorWithOffset, createInfo, vk::MemoryRequirement::Any));
1455     const vk::VkImage endImage                 = m_imageToImageCopy ? **copyImage : **image;
1456     de::MovePtr<BufferWithMemory> outputBuffer = de::MovePtr<BufferWithMemory>(
1457         new BufferWithMemory(vk, device, alloc, makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
1458                              MemoryRequirement::HostVisible));
1459 
1460     vk::Allocation &allocation = image->getAllocation();
1461     void *ptr                  = allocation.getHostPtr();
1462     generateData(ptr, bufferSize, m_format);
1463 
1464     vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties = {
1465         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT, // VkStructureType sType;
1466         DE_NULL,                                                              // void* pNext;
1467         0u,                                                                   // uint32_t copySrcLayoutCount;
1468         DE_NULL,                                                              // VkImageLayout* pCopySrcLayouts;
1469         0u,                                                                   // uint32_t copyDstLayoutCount;
1470         DE_NULL,                                                              // VkImageLayout* pCopyDstLayouts;
1471         {},    // uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE];
1472         false, // VkBool32 identicalMemoryTypeRequirements;
1473     };
1474     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1475     if (hostImageCopyProperties.identicalMemoryTypeRequirements)
1476     {
1477         createInfo.flags &= ~(vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT);
1478         de::MovePtr<ImageWithMemory> imageWithoutHostCopy = de::MovePtr<ImageWithMemory>(
1479             new ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::HostVisible));
1480         vk::VkMemoryRequirements hostImageMemoryRequirements;
1481         vk::VkMemoryRequirements memoryRequirements;
1482         vk.getImageMemoryRequirements(device, **image, &hostImageMemoryRequirements);
1483         vk.getImageMemoryRequirements(device, **imageWithoutHostCopy, &memoryRequirements);
1484 
1485         if (hostImageMemoryRequirements.memoryTypeBits != memoryRequirements.memoryTypeBits)
1486             TCU_THROW(NotSupportedError, "Layout not supported for src host copy");
1487     }
1488 
1489     // map device memory and initialize
1490     {
1491         const vk::VkHostImageLayoutTransitionInfoEXT transition = {
1492             vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT, // VkStructureType sType;
1493             DE_NULL,                                                     // const void* pNext;
1494             image->get(),                                                // VkImage image;
1495             vk::VK_IMAGE_LAYOUT_PREINITIALIZED,                          // VkImageLayout oldLayout;
1496             m_srcLayout,                                                 // VkImageLayout newLayout;
1497             subresourceRange                                             // VkImageSubresourceRange subresourceRange;
1498         };
1499         vk.transitionImageLayoutEXT(device, 1, &transition);
1500     }
1501 
1502     if (m_imageToImageCopy)
1503     {
1504         vk::VkHostImageLayoutTransitionInfoEXT transition = {
1505             vk::VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT, // VkStructureType sType;
1506             DE_NULL,                                                     // const void* pNext;
1507             copyImage->get(),                                            // VkImage image;
1508             vk::VK_IMAGE_LAYOUT_UNDEFINED,                               // VkImageLayout oldLayout;
1509             m_dstLayout,                                                 // VkImageLayout newLayout;
1510             subresourceRange                                             // VkImageSubresourceRange subresourceRange;
1511         };
1512         vk.transitionImageLayoutEXT(device, 1, &transition);
1513 
1514         const vk::VkImageCopy2KHR region = {
1515             vk::VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR, // VkStructureType sType;
1516             DE_NULL,                                // const void* pNext;
1517             subresourceLayers,                      // VkImageSubresourceLayers srcSubresource;
1518             offset,                                 // VkOffset3D srcOffset;
1519             subresourceLayers,                      // VkImageSubresourceLayers dstSubresource;
1520             offset,                                 // VkOffset3D dstOffset;
1521             m_size                                  // VkExtent3D extent;
1522         };
1523 
1524         const vk::VkHostImageCopyFlagsEXT hostImageCopyFlags =
1525             m_memcpy ? (vk::VkHostImageCopyFlagsEXT)vk::VK_HOST_IMAGE_COPY_MEMCPY_EXT : (vk::VkHostImageCopyFlagsEXT)0u;
1526 
1527         const vk::VkCopyImageToImageInfoEXT copyImageToImageInfo = {
1528             vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_IMAGE_INFO_EXT, // VkStructureType sType;
1529             DE_NULL,                                            // const void* pNext;
1530             hostImageCopyFlags,                                 // VkHostImageCopyFlagsEXT flags;
1531             **image,                                            // VkImage srcImage;
1532             m_srcLayout,                                        // VkImageLayout srcImageLayout;
1533             **copyImage,                                        // VkImage dstImage;
1534             m_dstLayout,                                        // VkImageLayout dstImageLayout;
1535             1u,                                                 // uint32_t regionCount;
1536             &region,                                            // const VkImageCopy2* pRegions;
1537         };
1538 
1539         vk.copyImageToImageEXT(device, &copyImageToImageInfo);
1540 
1541         transition.oldLayout = m_dstLayout;
1542         transition.newLayout = m_srcLayout;
1543         vk.transitionImageLayoutEXT(device, 1, &transition);
1544     }
1545 
1546     uint8_t *data = new uint8_t[bufferSize];
1547 
1548     const vk::VkImageToMemoryCopyEXT region = {
1549         vk::VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT, // VkStructureType sType;
1550         DE_NULL,                                        // const void* pNext;
1551         data,                                           // void* memoryHostPointer;
1552         0u,                                             // uint32_t memoryRowLength;
1553         0u,                                             // uint32_t memoryImageHeight;
1554         subresourceLayers,                              // VkImageSubresourceLayers imageSubresource;
1555         offset,                                         // VkOffset3D imageOffset;
1556         m_size,                                         // VkExtent3D imageExtent;
1557     };
1558 
1559     const vk::VkCopyImageToMemoryInfoEXT copyImageToMemoryInfo = {
1560         vk::VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT, // VkStructureType sType;
1561         DE_NULL,                                             // const void* pNext;
1562         0u,                                                  // VkMemoryImageCopyFlagsEXT flags;
1563         endImage,                                            // VkImage srcImage;
1564         m_srcLayout,                                         // VkImageLayout srcImageLayout;
1565         1,                                                   // uint32_t regionCount;
1566         &region,                                             // const VkImageToMemoryCopyEXT* pRegions;
1567     };
1568     vk.copyImageToMemoryEXT(device, &copyImageToMemoryInfo);
1569 
1570     vk::beginCommandBuffer(vk, *cmdBuffer);
1571     {
1572         auto imageMemoryBarrier =
1573             makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, m_srcLayout,
1574                                    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **image, subresourceRange);
1575         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_NONE, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1576                               DE_NULL, 0u, DE_NULL, 1, &imageMemoryBarrier);
1577 
1578         const vk::VkBufferImageCopy copyRegion = {
1579             0u,                // VkDeviceSize bufferOffset;
1580             0u,                // uint32_t bufferRowLength;
1581             0u,                // uint32_t bufferImageHeight;
1582             subresourceLayers, // VkImageSubresourceLayers imageSubresource;
1583             offset,            // VkOffset3D imageOffset;
1584             m_size             // VkExtent3D imageExtent;
1585         };
1586         vk.cmdCopyImageToBuffer(*cmdBuffer, **image, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **outputBuffer, 1u,
1587                                 &copyRegion);
1588     }
1589     vk::endCommandBuffer(vk, *cmdBuffer);
1590 
1591     vk::submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
1592     auto outputPtr = outputBuffer->getAllocation().getHostPtr();
1593     bool match     = memcmp(data, outputPtr, bufferSize) == 0;
1594 
1595     if (!match)
1596     {
1597         for (uint32_t i = 0; i < bufferSize; ++i)
1598         {
1599             if (data[i] != ((uint8_t *)outputPtr)[i])
1600             {
1601                 log << tcu::TestLog::Message << "At byte " << i << " data from vkCopyImageToMemoryEXT() is " << data[i]
1602                     << ", but data from vkCmdCopyImageToBuffer() is " << ((uint8_t *)outputPtr)[i]
1603                     << tcu::TestLog::EndMessage;
1604                 break;
1605             }
1606         }
1607     }
1608 
1609     delete[] data;
1610 
1611     if (!match)
1612     {
1613         return tcu::TestStatus::fail("Copies values do not match");
1614     }
1615 
1616     return tcu::TestStatus::pass("Pass");
1617 }
1618 
1619 class PreinitializedTestCase : public vkt::TestCase
1620 {
1621 public:
PreinitializedTestCase(tcu::TestContext & context,const char * name,const vk::VkFormat format,vk::VkImageLayout srcLayout,vk::VkImageLayout dstLayout,vk::VkExtent3D size,uint32_t arrayLayers,bool imageToImageCopy,bool memcpy,vk::VkImageTiling tiling,uint32_t offset)1622     PreinitializedTestCase(tcu::TestContext &context, const char *name, const vk::VkFormat format,
1623                            vk::VkImageLayout srcLayout, vk::VkImageLayout dstLayout, vk::VkExtent3D size,
1624                            uint32_t arrayLayers, bool imageToImageCopy, bool memcpy, vk::VkImageTiling tiling,
1625                            uint32_t offset)
1626         : TestCase(context, name)
1627         , m_format(format)
1628         , m_srcLayout(srcLayout)
1629         , m_dstLayout(dstLayout)
1630         , m_size(size)
1631         , m_arrayLayers(arrayLayers)
1632         , m_imageToImageCopy(imageToImageCopy)
1633         , m_memcpy(memcpy)
1634         , m_tiling(tiling)
1635         , m_offset(offset)
1636     {
1637     }
1638 
1639 private:
1640     void checkSupport(vkt::Context &context) const;
createInstance(vkt::Context & context) const1641     vkt::TestInstance *createInstance(vkt::Context &context) const
1642     {
1643         return new PreinitializedTestInstance(context, m_format, m_srcLayout, m_dstLayout, m_size, m_arrayLayers,
1644                                               m_imageToImageCopy, m_memcpy, m_tiling, m_offset);
1645     }
1646 
1647     const vk::VkFormat m_format;
1648     const vk::VkImageLayout m_srcLayout;
1649     const vk::VkImageLayout m_dstLayout;
1650     const vk::VkExtent3D m_size;
1651     const uint32_t m_arrayLayers;
1652     const bool m_imageToImageCopy;
1653     const bool m_memcpy;
1654     const vk::VkImageTiling m_tiling;
1655     const uint32_t m_offset;
1656 };
1657 
checkSupport(vkt::Context & context) const1658 void PreinitializedTestCase::checkSupport(vkt::Context &context) const
1659 {
1660     vk::VkInstance instance(context.getInstance());
1661     vk::InstanceDriver instanceDriver(context.getPlatformInterface(), instance);
1662     const InstanceInterface &vki        = context.getInstanceInterface();
1663     vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1664 
1665     context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1666 
1667     if (m_tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1668         context.requireDeviceFunctionality("VK_EXT_image_drm_format_modifier");
1669 
1670     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || m_dstLayout == vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
1671         context.requireDeviceFunctionality("VK_KHR_swapchain");
1672 
1673     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ||
1674         m_dstLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL ||
1675         m_srcLayout == vk::VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR ||
1676         m_dstLayout == vk::VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR)
1677         context.requireDeviceFunctionality("VK_KHR_maintenance2");
1678 
1679     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1680         m_dstLayout == vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL ||
1681         m_srcLayout == vk::VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL ||
1682         m_dstLayout == vk::VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL ||
1683         m_srcLayout == vk::VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL ||
1684         m_dstLayout == vk::VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)
1685         context.requireDeviceFunctionality("VK_KHR_separate_depth_stencil_layouts");
1686 
1687     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL ||
1688         m_srcLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL || m_dstLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL)
1689         context.requireDeviceFunctionality("VK_KHR_synchronization2");
1690 
1691     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT ||
1692         m_dstLayout == vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT)
1693         context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
1694 
1695     vk::VkPhysicalDeviceHostImageCopyFeaturesEXT hostImageCopyFeatures = {
1696         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT, // VkStructureType                    sType
1697         DE_NULL,                                                            // const void*                        pNext
1698         VK_FALSE,                                                           // VkBool32 hostImageCopy;
1699     };
1700 
1701     vk::VkPhysicalDeviceFeatures features;
1702     deMemset(&features, 0, sizeof(vk::VkPhysicalDeviceFeatures));
1703     vk::VkPhysicalDeviceFeatures2 features2 = {
1704         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType                    sType
1705         &hostImageCopyFeatures,                           // const void*                        pNext
1706         features                                          // VkPhysicalDeviceFeatures            features
1707     };
1708 
1709     instanceDriver.getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
1710 
1711     vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties = {
1712         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT, // VkStructureType sType;
1713         DE_NULL,                                                              // void* pNext;
1714         0u,                                                                   // uint32_t copySrcLayoutCount;
1715         DE_NULL,                                                              // VkImageLayout* pCopySrcLayouts;
1716         0u,                                                                   // uint32_t copyDstLayoutCount;
1717         DE_NULL,                                                              // VkImageLayout* pCopyDstLayouts;
1718         {},   // uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE];
1719         false // VkBool32 identicalMemoryTypeRequirements;
1720     };
1721 
1722     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1723     std::vector<vk::VkImageLayout> srcLayouts(hostImageCopyProperties.copySrcLayoutCount);
1724     std::vector<vk::VkImageLayout> dstLayouts(hostImageCopyProperties.copyDstLayoutCount);
1725     hostImageCopyProperties.pCopySrcLayouts = srcLayouts.data();
1726     hostImageCopyProperties.pCopyDstLayouts = dstLayouts.data();
1727     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1728 
1729     bool layoutSupported = false;
1730     for (uint32_t i = 0; i < hostImageCopyProperties.copySrcLayoutCount; ++i)
1731     {
1732         if (hostImageCopyProperties.pCopySrcLayouts[i] == m_srcLayout)
1733             layoutSupported = true;
1734     }
1735     if (layoutSupported == false)
1736         TCU_THROW(NotSupportedError, "Layout not supported for src host copy");
1737     layoutSupported = false;
1738     for (uint32_t i = 0; i < hostImageCopyProperties.copyDstLayoutCount; ++i)
1739     {
1740         if (hostImageCopyProperties.pCopyDstLayouts[i] == m_dstLayout)
1741             layoutSupported = true;
1742     }
1743     if (layoutSupported == false)
1744         TCU_THROW(NotSupportedError, "Layout not supported for dst host copy");
1745 
1746     if (hostImageCopyFeatures.hostImageCopy != VK_TRUE)
1747         TCU_THROW(NotSupportedError, "hostImageCopy not supported");
1748 
1749     uint64_t modifier = 0;
1750     checkSupportedFormatFeatures(instanceDriver, physicalDevice, m_format, m_tiling, &modifier);
1751 
1752     vk::VkImageType const imageType                    = m_size.depth > 1 ? vk::VK_IMAGE_TYPE_3D : vk::VK_IMAGE_TYPE_2D;
1753     vk::VkImageFormatProperties2 imageFormatProperties = {
1754         vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, // VkStructureType sType;
1755         DE_NULL,                                         // void* pNext;
1756         {},                                              // VkImageFormatProperties imageFormatProperties;
1757     };
1758     vk::VkPhysicalDeviceImageDrmFormatModifierInfoEXT modifierInfo = {
1759         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, // VkStructureType sType;
1760         DE_NULL,                                                                  // const void* pNext;
1761         modifier,                                                                 // uint64_t drmFormatModifier;
1762         VK_SHARING_MODE_EXCLUSIVE,                                                // VkSharingMode sharingMode;
1763         0u,                                                                       // uint32_t queueFamilyIndexCount;
1764         DE_NULL // const uint32_t* pQueueFamilyIndices;
1765     };
1766 
1767     vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1768     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
1769         usage |= vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1770     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
1771         usage |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;
1772     if (m_srcLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
1773         usage |= vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1774 
1775     vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
1776         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,                         // VkStructureType sType;
1777         m_tiling == vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ? &modifierInfo : DE_NULL, // const void* pNext;
1778         m_format,                                                                          // VkFormat format;
1779         imageType,                                                                         // VkImageType type;
1780         m_tiling,                                                                          // VkImageTiling tiling;
1781         usage,                                                                             // VkImageUsageFlags usage;
1782         (vk::VkImageCreateFlags)0u                                                         // VkImageCreateFlags flags;
1783     };
1784     if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageFormatProperties) ==
1785         vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1786         TCU_THROW(NotSupportedError, "Image format not supported.");
1787     if (imageFormatProperties.imageFormatProperties.maxArrayLayers < m_arrayLayers)
1788         TCU_THROW(NotSupportedError, "Required image array layers not supported.");
1789 }
1790 
1791 class PropertiesTestInstance : public vkt::TestInstance
1792 {
1793 public:
PropertiesTestInstance(vkt::Context & context)1794     PropertiesTestInstance(vkt::Context &context) : vkt::TestInstance(context)
1795     {
1796     }
1797 
1798 private:
1799     tcu::TestStatus iterate(void);
1800 };
1801 
iterate(void)1802 tcu::TestStatus PropertiesTestInstance::iterate(void)
1803 {
1804     vk::VkInstance instance(m_context.getInstance());
1805     vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
1806     vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1807 
1808     vk::VkPhysicalDeviceHostImageCopyPropertiesEXT hostImageCopyProperties = {
1809         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES_EXT, // VkStructureType sType;
1810         DE_NULL,                                                              // void* pNext;
1811         0u,                                                                   // uint32_t copySrcLayoutCount;
1812         DE_NULL,                                                              // VkImageLayout* pCopySrcLayouts;
1813         0u,                                                                   // uint32_t copyDstLayoutCount;
1814         DE_NULL,                                                              // VkImageLayout* pCopyDstLayouts;
1815         {},   // uint8_t optimalTilingLayoutUUID[VK_UUID_SIZE];
1816         false // VkBool32 identicalMemoryTypeRequirements;
1817     };
1818     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1819     std::vector<vk::VkImageLayout> srcLayouts(hostImageCopyProperties.copySrcLayoutCount);
1820     std::vector<vk::VkImageLayout> dstLayouts(hostImageCopyProperties.copyDstLayoutCount);
1821     hostImageCopyProperties.pCopySrcLayouts = srcLayouts.data();
1822     hostImageCopyProperties.pCopyDstLayouts = dstLayouts.data();
1823     getHostImageCopyProperties(instanceDriver, physicalDevice, &hostImageCopyProperties);
1824 
1825     if (hostImageCopyProperties.copySrcLayoutCount == 0)
1826         return tcu::TestStatus::fail("copySrcLayoutCount is 0");
1827     if (hostImageCopyProperties.copyDstLayoutCount == 0)
1828         return tcu::TestStatus::fail("copyDstLayoutCount is 0");
1829 
1830     bool layoutSupported = false;
1831     for (uint32_t i = 0; i < hostImageCopyProperties.copySrcLayoutCount; ++i)
1832     {
1833         if (hostImageCopyProperties.pCopySrcLayouts[i] == vk::VK_IMAGE_LAYOUT_GENERAL)
1834             layoutSupported = true;
1835     }
1836     if (layoutSupported == false)
1837         return tcu::TestStatus::fail("VK_IMAGE_LAYOUT_GENERAL not supported for src host copy");
1838     layoutSupported = false;
1839     for (uint32_t i = 0; i < hostImageCopyProperties.copyDstLayoutCount; ++i)
1840     {
1841         if (hostImageCopyProperties.pCopyDstLayouts[i] == vk::VK_IMAGE_LAYOUT_GENERAL)
1842             layoutSupported = true;
1843     }
1844     if (layoutSupported == false)
1845         return tcu::TestStatus::fail("VK_IMAGE_LAYOUT_GENERAL not supported for dst host copy");
1846 
1847     return tcu::TestStatus::pass("Pass");
1848 }
1849 
1850 class PropertiesTestCase : public vkt::TestCase
1851 {
1852 public:
PropertiesTestCase(tcu::TestContext & context,const char * name)1853     PropertiesTestCase(tcu::TestContext &context, const char *name) : TestCase(context, name)
1854     {
1855     }
1856 
1857 private:
createInstance(vkt::Context & context) const1858     vkt::TestInstance *createInstance(vkt::Context &context) const
1859     {
1860         return new PropertiesTestInstance(context);
1861     }
1862     void checkSupport(vkt::Context &context) const;
1863 };
1864 
checkSupport(vkt::Context & context) const1865 void PropertiesTestCase::checkSupport(vkt::Context &context) const
1866 {
1867     context.requireDeviceFunctionality("VK_EXT_host_image_copy");
1868 }
1869 
1870 class QueryTestInstance : public vkt::TestInstance
1871 {
1872 public:
QueryTestInstance(vkt::Context & context,const vk::VkFormat format,const vk::VkImageTiling tiling)1873     QueryTestInstance(vkt::Context &context, const vk::VkFormat format, const vk::VkImageTiling tiling)
1874         : vkt::TestInstance(context)
1875         , m_format(format)
1876         , m_tiling(tiling)
1877     {
1878     }
1879 
1880 private:
1881     tcu::TestStatus iterate(void);
1882 
1883     const vk::VkFormat m_format;
1884     const vk::VkImageTiling m_tiling;
1885 };
1886 
iterate(void)1887 tcu::TestStatus QueryTestInstance::iterate(void)
1888 {
1889     const InstanceInterface &vki              = m_context.getInstanceInterface();
1890     const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1891     tcu::TestLog &log                         = m_context.getTestContext().getLog();
1892 
1893     const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
1894         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType;
1895         DE_NULL,                                                   // const void* pNext;
1896         m_format,                                                  // VkFormat format;
1897         vk::VK_IMAGE_TYPE_2D,                                      // VkImageType type;
1898         m_tiling,                                                  // VkImageTiling tiling;
1899         vk::VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT,                  // VkImageUsageFlags usage;
1900         (VkImageCreateFlags)0u                                     // VkImageCreateFlags flags;
1901     };
1902 
1903     vk::VkHostImageCopyDevicePerformanceQueryEXT hostImageCopyDevicePerformanceQuery = vk::initVulkanStructure();
1904     vk::VkImageFormatProperties2 imageFormatProperties = vk::initVulkanStructure(&hostImageCopyDevicePerformanceQuery);
1905     vk::VkResult res =
1906         vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageFormatProperties);
1907 
1908     if (hostImageCopyDevicePerformanceQuery.identicalMemoryLayout == VK_FALSE)
1909     {
1910         if (hostImageCopyDevicePerformanceQuery.optimalDeviceAccess != VK_FALSE)
1911         {
1912             log << tcu::TestLog::Message
1913                 << "VkHostImageCopyDevicePerformanceQueryEXT::identicalMemoryLayout is VK_FALSE, but "
1914                    "VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess is VK_TRUE"
1915                 << tcu::TestLog::EndMessage;
1916             return tcu::TestStatus::fail("Fail");
1917         }
1918     }
1919     else
1920     {
1921         if (hostImageCopyDevicePerformanceQuery.optimalDeviceAccess != VK_TRUE)
1922         {
1923             log << tcu::TestLog::Message
1924                 << "VkHostImageCopyDevicePerformanceQueryEXT::identicalMemoryLayout is VK_TRUE, but "
1925                    "VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess is VK_FALSE"
1926                 << tcu::TestLog::EndMessage;
1927             return tcu::TestStatus::fail("Fail");
1928         }
1929     }
1930 
1931     if (isBlockCompressedFormat(m_format) && res == vk::VK_SUCCESS)
1932     {
1933         if (hostImageCopyDevicePerformanceQuery.optimalDeviceAccess != VK_TRUE)
1934         {
1935             log << tcu::TestLog::Message
1936                 << "Format is a block compressed format and vkGetPhysicalDeviceImageFormatProperties2 returned "
1937                    "VK_SUCCESS, but VkHostImageCopyDevicePerformanceQueryEXT::optimalDeviceAccess is VK_FALSE"
1938                 << tcu::TestLog::EndMessage;
1939             return tcu::TestStatus::fail("Fail");
1940         }
1941     }
1942 
1943     if (!vk::isDepthStencilFormat(m_format))
1944     {
1945         vk::VkFormatProperties3 formatProperties3 = vk::initVulkanStructure();
1946         vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
1947         vki.getPhysicalDeviceFormatProperties2(physicalDevice, m_format, &formatProperties2);
1948 
1949         if (m_tiling == VK_IMAGE_TILING_OPTIMAL)
1950         {
1951             if ((formatProperties3.optimalTilingFeatures & VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1952             {
1953                 log << tcu::TestLog::Message
1954                     << "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT is supported in optimalTilingFeatures for format "
1955                     << vk::getFormatStr(m_format).toString()
1956                     << ", but VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT is not" << tcu::TestLog::EndMessage;
1957                 return tcu::TestStatus::fail("VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT not supported");
1958             }
1959         }
1960         else if (m_tiling == VK_IMAGE_TILING_LINEAR)
1961         {
1962             if ((formatProperties3.linearTilingFeatures & VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT) == 0)
1963             {
1964                 log << tcu::TestLog::Message
1965                     << "VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT is supported in linearTilingFeatures for format "
1966                     << vk::getFormatStr(m_format).toString()
1967                     << ", but VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT is not" << tcu::TestLog::EndMessage;
1968                 return tcu::TestStatus::fail("VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT not supported");
1969             }
1970         }
1971     }
1972 
1973     return tcu::TestStatus::pass("Pass");
1974 }
1975 
1976 class QueryTestCase : public vkt::TestCase
1977 {
1978 public:
QueryTestCase(tcu::TestContext & context,const char * name,const vk::VkFormat format,const vk::VkImageTiling tiling)1979     QueryTestCase(tcu::TestContext &context, const char *name, const vk::VkFormat format,
1980                   const vk::VkImageTiling tiling)
1981         : TestCase(context, name)
1982         , m_format(format)
1983         , m_tiling(tiling)
1984     {
1985     }
1986 
1987 private:
createInstance(vkt::Context & context) const1988     vkt::TestInstance *createInstance(vkt::Context &context) const
1989     {
1990         return new QueryTestInstance(context, m_format, m_tiling);
1991     }
1992     void checkSupport(vkt::Context &context) const;
1993 
1994     const vk::VkFormat m_format;
1995     const vk::VkImageTiling m_tiling;
1996 };
1997 
checkSupport(vkt::Context & context) const1998 void QueryTestCase::checkSupport(vkt::Context &context) const
1999 {
2000     const InstanceInterface &vki = context.getInstanceInterface();
2001 
2002     context.requireDeviceFunctionality("VK_EXT_host_image_copy");
2003 
2004     vk::VkFormatProperties3 formatProperties3 = vk::initVulkanStructure();
2005     vk::VkFormatProperties2 formatProperties2 = vk::initVulkanStructure(&formatProperties3);
2006     vki.getPhysicalDeviceFormatProperties2(context.getPhysicalDevice(), m_format, &formatProperties2);
2007     if (m_tiling == VK_IMAGE_TILING_OPTIMAL &&
2008         (formatProperties3.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) == 0)
2009         TCU_THROW(NotSupportedError, "Format feature sampled image bit not supported for optimal tiling.");
2010     if (m_tiling == VK_IMAGE_TILING_LINEAR &&
2011         (formatProperties3.linearTilingFeatures & vk::VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) == 0)
2012         TCU_THROW(NotSupportedError, "Format feature sampled image bit not supported for linear tiling.");
2013 }
2014 
2015 class IdenticalMemoryLayoutTestInstance : public vkt::TestInstance
2016 {
2017 public:
IdenticalMemoryLayoutTestInstance(vkt::Context & context,const vk::VkFormat format,const vk::VkImageTiling tiling)2018     IdenticalMemoryLayoutTestInstance(vkt::Context &context, const vk::VkFormat format, const vk::VkImageTiling tiling)
2019         : vkt::TestInstance(context)
2020         , m_format(format)
2021         , m_tiling(tiling)
2022     {
2023     }
2024 
2025 private:
2026     tcu::TestStatus iterate(void);
2027 
2028     const vk::VkFormat m_format;
2029     const vk::VkImageTiling m_tiling;
2030 };
2031 
generateImageData(const DeviceInterface & vkd,VkDevice device,vk::Allocator & alloc,uint32_t qfIndex,VkQueue queue,VkImage image,VkFormat format,const tcu::IVec3 & extent)2032 void generateImageData(const DeviceInterface &vkd, VkDevice device, vk::Allocator &alloc, uint32_t qfIndex,
2033                        VkQueue queue, VkImage image, VkFormat format, const tcu::IVec3 &extent)
2034 {
2035     const auto tcuFormat = mapVkFormat(format);
2036     const auto vkExtent  = makeExtent3D(extent);
2037     tcu::TextureLevel level(tcuFormat, extent.x(), extent.y());
2038     auto access        = level.getAccess();
2039     const auto chClass = tcu::getTextureChannelClass(tcuFormat.type);
2040     const tcu::Vec4 minValue(0.0f);
2041     tcu::Vec4 maxValue(1.0f);
2042 
2043     //
2044     // Generate image data on host memory.
2045     //
2046 
2047     if (tcuFormat.order == tcu::TextureFormat::S)
2048     {
2049         // Stencil-only is stored in the first component. Stencil is always 8 bits.
2050         maxValue.x() = 1 << 8;
2051     }
2052     else if (tcuFormat.order == tcu::TextureFormat::DS)
2053     {
2054         // In a combined format, fillWithComponentGradients expects stencil in the fourth component.
2055         maxValue.w() = 1 << 8;
2056     }
2057     else if (chClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || chClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2058     {
2059         // The tcu::Vectors we use as pixels are 32-bit, so clamp to that.
2060         const tcu::IVec4 bits = tcu::min(tcu::getTextureFormatBitDepth(tcuFormat), tcu::IVec4(32));
2061         const int signBit     = (chClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? 1 : 0);
2062 
2063         for (int i = 0; i < 4; ++i)
2064         {
2065             if (bits[i] != 0)
2066                 maxValue[i] = static_cast<float>((uint64_t(1) << (bits[i] - signBit)) - 1);
2067         }
2068     }
2069 
2070     tcu::fillWithComponentGradients2(access, minValue, maxValue);
2071 
2072     //
2073     // Upload generated data to the image.
2074     //
2075 
2076     if (isDepthStencilFormat(format))
2077     {
2078         // Iteration index: 0 is depth, 1 is stencil
2079         for (int i = 0; i < 2; ++i)
2080         {
2081             const auto hasComponent =
2082                 ((i == 0) ? tcu::hasDepthComponent(tcuFormat.order) : tcu::hasStencilComponent(tcuFormat.order));
2083             const auto origMode    = ((i == 0) ? tcu::Sampler::MODE_DEPTH : tcu::Sampler::MODE_STENCIL);
2084             const auto layerAspect = ((i == 0) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT);
2085 
2086             if (hasComponent)
2087             {
2088                 const auto xferFormat = ((i == 0) ? getDepthCopyFormat(format) : getStencilCopyFormat(format));
2089                 auto origAccess       = tcu::getEffectiveDepthStencilAccess(access, origMode);
2090                 tcu::TextureLevel copyLevel(xferFormat, extent.x(), extent.y());
2091                 auto copyAccess       = copyLevel.getAccess();
2092                 const auto pixelSize  = tcu::getPixelSize(xferFormat);
2093                 const auto bufferSize = pixelSize * extent.x() * extent.y();
2094 
2095                 // Get a copy of the aspect.
2096                 tcu::copy(copyAccess, origAccess);
2097 
2098                 // Upload that copy to a buffer and then the image.
2099                 const auto bufferInfo =
2100                     makeBufferCreateInfo(static_cast<VkDeviceSize>(bufferSize), VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2101                 BufferWithMemory srcBuffer(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible);
2102                 auto &srcBufferAlloc = srcBuffer.getAllocation();
2103                 void *srcBufferData  = srcBufferAlloc.getHostPtr();
2104 
2105                 deMemcpy(srcBufferData, copyAccess.getDataPtr(), static_cast<size_t>(bufferSize));
2106                 flushAlloc(vkd, device, srcBufferAlloc);
2107 
2108                 const auto cmdPool   = makeCommandPool(vkd, device, qfIndex);
2109                 const auto cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2110 
2111                 beginCommandBuffer(vkd, *cmdBuffer);
2112 
2113                 const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
2114                 cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2115                                          VK_PIPELINE_STAGE_TRANSFER_BIT, &barrier);
2116 
2117                 const auto copySRL    = makeImageSubresourceLayers(layerAspect, 0u, 0u, 1u);
2118                 const auto copyRegion = makeBufferImageCopy(vkExtent, copySRL);
2119                 vkd.cmdCopyBufferToImage(*cmdBuffer, srcBuffer.get(), image, VK_IMAGE_LAYOUT_GENERAL, 1u, &copyRegion);
2120 
2121                 endCommandBuffer(vkd, *cmdBuffer);
2122                 submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
2123             }
2124         }
2125     }
2126     else
2127     {
2128         // Simplest case.
2129         const auto pixelSize  = tcu::getPixelSize(tcuFormat);
2130         const auto bufferSize = pixelSize * extent.x() * extent.y();
2131 
2132         // Upload pixels to host-visible buffer.
2133         const auto bufferInfo =
2134             makeBufferCreateInfo(static_cast<VkDeviceSize>(bufferSize), VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2135         BufferWithMemory srcBuffer(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible);
2136         auto &srcBufferAlloc = srcBuffer.getAllocation();
2137         void *srcBufferData  = srcBufferAlloc.getHostPtr();
2138 
2139         deMemcpy(srcBufferData, access.getDataPtr(), static_cast<size_t>(bufferSize));
2140         flushAlloc(vkd, device, srcBufferAlloc);
2141 
2142         const auto cmdPool   = makeCommandPool(vkd, device, qfIndex);
2143         const auto cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2144 
2145         beginCommandBuffer(vkd, *cmdBuffer);
2146         const auto copySRL    = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2147         const auto copyRegion = makeBufferImageCopy(vkExtent, copySRL);
2148         vkd.cmdCopyBufferToImage(*cmdBuffer, srcBuffer.get(), image, VK_IMAGE_LAYOUT_GENERAL, 1u, &copyRegion);
2149 
2150         endCommandBuffer(vkd, *cmdBuffer);
2151         submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
2152     }
2153 }
2154 
2155 // This is slightly special.
generateCompressedImageData(const DeviceInterface & vkd,VkDevice device,vk::Allocator & alloc,uint32_t qfIndex,VkQueue queue,VkImage image,VkFormat format,const tcu::IVec3 & extent)2156 void generateCompressedImageData(const DeviceInterface &vkd, VkDevice device, vk::Allocator &alloc, uint32_t qfIndex,
2157                                  VkQueue queue, VkImage image, VkFormat format, const tcu::IVec3 &extent)
2158 {
2159     const auto vkExtent  = makeExtent3D(extent);
2160     const auto tcuFormat = mapVkCompressedFormat(format);
2161     tcu::CompressedTexture texture(tcuFormat, extent.x(), extent.y());
2162     const auto dataSize = texture.getDataSize();
2163     auto dataPtr        = reinterpret_cast<uint8_t *>(texture.getData());
2164 
2165     // This is supposed to be safe for the compressed formats we're using (no ASTC, no ETC, no SFLOAT formats).
2166     de::Random rnd(static_cast<uint32_t>(format));
2167     for (int i = 0; i < dataSize; ++i)
2168         dataPtr[i] = rnd.getUint8();
2169 
2170     // Upload pixels to host-visible buffer.
2171     const auto bufferInfo = makeBufferCreateInfo(static_cast<VkDeviceSize>(dataSize), VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
2172     BufferWithMemory srcBuffer(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible);
2173     auto &srcBufferAlloc = srcBuffer.getAllocation();
2174     void *srcBufferData  = srcBufferAlloc.getHostPtr();
2175 
2176     deMemcpy(srcBufferData, texture.getData(), static_cast<size_t>(dataSize));
2177     flushAlloc(vkd, device, srcBufferAlloc);
2178 
2179     // Transfer buffer to compressed image.
2180     const auto cmdPool   = makeCommandPool(vkd, device, qfIndex);
2181     const auto cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2182 
2183     beginCommandBuffer(vkd, *cmdBuffer);
2184     const auto copySRL    = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2185     const auto copyRegion = makeBufferImageCopy(vkExtent, copySRL);
2186     vkd.cmdCopyBufferToImage(*cmdBuffer, srcBuffer.get(), image, VK_IMAGE_LAYOUT_GENERAL, 1u, &copyRegion);
2187 
2188     endCommandBuffer(vkd, *cmdBuffer);
2189     submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
2190 }
2191 
iterate(void)2192 tcu::TestStatus IdenticalMemoryLayoutTestInstance::iterate(void)
2193 {
2194     const InstanceInterface &vki          = m_context.getInstanceInterface();
2195     const DeviceInterface &vk             = m_context.getDeviceInterface();
2196     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
2197     const VkDevice device                 = m_context.getDevice();
2198     const auto memoryProperties           = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
2199     const uint32_t queueFamilyIndex       = m_context.getUniversalQueueFamilyIndex();
2200     const VkQueue queue                   = m_context.getUniversalQueue();
2201     auto &alloc                           = m_context.getDefaultAllocator();
2202     const tcu::IVec3 extent(32, 32, 1);
2203     const auto vkExtent           = makeExtent3D(extent);
2204     const auto baseUsageFlags     = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2205     const auto extendedUsageFlags = (baseUsageFlags | VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT);
2206 
2207     // Create two images, one with the host transfer usage bit and another one without it, to check identicalMemoryLayout.
2208     VkImageCreateInfo imageCreateInfo = {
2209         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
2210         nullptr,                                 // const void*                pNext
2211         0u,                                      // VkImageCreateFlags        flags
2212         VK_IMAGE_TYPE_2D,                        // VkImageType                imageType
2213         m_format,                                // VkFormat                    format
2214         vkExtent,                                // VkExtent3D                extent
2215         1u,                                      // uint32_t                    mipLevels
2216         1u,                                      // uint32_t                    arrayLayers
2217         VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits    samples
2218         m_tiling,                                // VkImageTiling            tiling
2219         baseUsageFlags,                          // VkImageUsageFlags        usage
2220         VK_SHARING_MODE_EXCLUSIVE,               // VkSharingMode            sharingMode
2221         0u,                                      // uint32_t                    queueFamilyIndexCount
2222         nullptr,                                 // const uint32_t*            pQueueFamilyIndices
2223         VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout            initialLayout
2224     };
2225     const auto baseImage     = createImage(vk, device, &imageCreateInfo);
2226     imageCreateInfo.usage    = extendedUsageFlags;
2227     const auto hostXferImage = createImage(vk, device, &imageCreateInfo);
2228 
2229     // Check memory requirements for both (size must match).
2230     const auto baseMemReqs  = getImageMemoryRequirements(vk, device, *baseImage);
2231     const auto hostXferReqs = getImageMemoryRequirements(vk, device, *hostXferImage);
2232 
2233     if (baseMemReqs.size != hostXferReqs.size)
2234         TCU_FAIL("Different memory sizes for normal and host-transfer image");
2235 
2236     const auto imageMemSize   = baseMemReqs.size;
2237     const auto imageMemSizeSz = static_cast<size_t>(imageMemSize);
2238 
2239     // Create two buffers that will share memory with the previous images.
2240     const auto bufferCreateInfo =
2241         makeBufferCreateInfo(imageMemSize, (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2242     const auto baseBuffer     = createBuffer(vk, device, &bufferCreateInfo);
2243     const auto hostXferBuffer = createBuffer(vk, device, &bufferCreateInfo);
2244 
2245     // Find common memory types for images and buffers and allocate memory.
2246     const auto baseBufferMemReqs     = getBufferMemoryRequirements(vk, device, *baseBuffer);
2247     const auto baseCommonMemoryTypes = (baseMemReqs.memoryTypeBits & baseBufferMemReqs.memoryTypeBits);
2248 
2249     // Very unlikely.
2250     if (baseCommonMemoryTypes == 0u)
2251         TCU_THROW(NotSupportedError, "Base buffer and image do not have any memory types in common");
2252 
2253     const auto baseSelectedMemType =
2254         selectMatchingMemoryType(memoryProperties, baseCommonMemoryTypes, MemoryRequirement::Any);
2255 
2256     const auto hostXferBufferMemReqs     = getBufferMemoryRequirements(vk, device, *hostXferBuffer);
2257     const auto hostXferCommonMemoryTypes = (hostXferReqs.memoryTypeBits & hostXferBufferMemReqs.memoryTypeBits);
2258 
2259     // Very unlikely.
2260     if (hostXferCommonMemoryTypes == 0u)
2261         TCU_THROW(NotSupportedError, "Host transfer buffer and image do not have any memory types in common");
2262 
2263     const auto hostXferSelectedMemType =
2264         selectMatchingMemoryType(memoryProperties, hostXferCommonMemoryTypes, MemoryRequirement::Any);
2265 
2266     VkMemoryAllocateInfo memoryAllocateInfo = {
2267         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
2268         nullptr,                                // const void* pNext;
2269         imageMemSize,                           // VkDeviceSize allocationSize;
2270         baseSelectedMemType,                    // uint32_t memoryTypeIndex;
2271     };
2272     const auto baseMemory              = allocateMemory(vk, device, &memoryAllocateInfo, nullptr);
2273     memoryAllocateInfo.memoryTypeIndex = hostXferSelectedMemType;
2274     const auto hostXferMemory          = allocateMemory(vk, device, &memoryAllocateInfo, nullptr);
2275 
2276     // Map allocations to images and buffers.
2277     vk.bindImageMemory(device, *baseImage, *baseMemory, 0u);
2278     vk.bindBufferMemory(device, *baseBuffer, *baseMemory, 0u);
2279 
2280     vk.bindImageMemory(device, *hostXferImage, *hostXferMemory, 0u);
2281     vk.bindBufferMemory(device, *hostXferBuffer, *hostXferMemory, 0u);
2282 
2283     // Clear both image memories to zero (via the memory-sharing buffers above) before filling images with data.
2284     {
2285         const auto cmdPool   = makeCommandPool(vk, device, queueFamilyIndex);
2286         const auto cmdbuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2287 
2288         // Transition both images to the general layout for subsequent operations.
2289         const auto isDepthStencil = isDepthStencilFormat(m_format);
2290         const auto tcuFormat      = (isCompressedFormat(m_format) ? tcu::TextureFormat() : mapVkFormat(m_format));
2291         const auto hasDepth       = isDepthStencil && tcu::hasDepthComponent(tcuFormat.order);
2292         const auto hasStencil     = isDepthStencil && tcu::hasStencilComponent(tcuFormat.order);
2293         const auto aspectMask =
2294             (isDepthStencil ?
2295                  ((hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) | (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)) :
2296                  VK_IMAGE_ASPECT_COLOR_BIT);
2297         const auto imageSRR = makeImageSubresourceRange(aspectMask, 0u, 1u, 0u, 1u);
2298 
2299         beginCommandBuffer(vk, *cmdbuffer);
2300         vk.cmdFillBuffer(*cmdbuffer, *baseBuffer, 0ull, VK_WHOLE_SIZE, 0u);
2301         vk.cmdFillBuffer(*cmdbuffer, *hostXferBuffer, 0ull, VK_WHOLE_SIZE, 0u);
2302         const std::vector<VkImageMemoryBarrier> transitionBarriers{
2303             makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
2304                                    VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, *baseImage, imageSRR),
2305             makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
2306                                    VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, *hostXferImage, imageSRR),
2307         };
2308         vk.cmdPipelineBarrier(*cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
2309                               nullptr, 0u, nullptr, de::sizeU32(transitionBarriers),
2310                               de::dataOrNull(transitionBarriers));
2311         endCommandBuffer(vk, *cmdbuffer);
2312         submitCommandsAndWait(vk, device, queue, *cmdbuffer);
2313     }
2314 
2315     // Generate data for both images.
2316     if (isCompressedFormat(m_format))
2317     {
2318         generateCompressedImageData(vk, device, alloc, queueFamilyIndex, queue, *baseImage, m_format, extent);
2319         generateCompressedImageData(vk, device, alloc, queueFamilyIndex, queue, *hostXferImage, m_format, extent);
2320     }
2321     else
2322     {
2323         generateImageData(vk, device, alloc, queueFamilyIndex, queue, *baseImage, m_format, extent);
2324         generateImageData(vk, device, alloc, queueFamilyIndex, queue, *hostXferImage, m_format, extent);
2325     }
2326 
2327     // Create a couple of host-visible buffers for verification.
2328     const auto verifBufferCreateInfo = makeBufferCreateInfo(imageMemSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2329     BufferWithMemory baseVerifBuffer(vk, device, alloc, verifBufferCreateInfo, MemoryRequirement::HostVisible);
2330     BufferWithMemory hostXferVerifBuffer(vk, device, alloc, verifBufferCreateInfo, MemoryRequirement::HostVisible);
2331 
2332     // Copy data from shared-memory buffers to verification buffers.
2333     const auto cmdPool         = makeCommandPool(vk, device, queueFamilyIndex);
2334     const auto cmdBuffer       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2335     const auto copyRegion      = makeBufferCopy(0ull, 0ull, imageMemSize);
2336     const auto preCopyBarrier  = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
2337     const auto postCopyBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2338 
2339     beginCommandBuffer(vk, *cmdBuffer);
2340     cmdPipelineMemoryBarrier(vk, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2341                              &preCopyBarrier);
2342     vk.cmdCopyBuffer(*cmdBuffer, *baseBuffer, *baseVerifBuffer, 1u, &copyRegion);
2343     vk.cmdCopyBuffer(*cmdBuffer, *hostXferBuffer, *hostXferVerifBuffer, 1u, &copyRegion);
2344     cmdPipelineMemoryBarrier(vk, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2345                              &postCopyBarrier);
2346     endCommandBuffer(vk, *cmdBuffer);
2347     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2348 
2349     invalidateAlloc(vk, device, baseVerifBuffer.getAllocation());
2350     invalidateAlloc(vk, device, hostXferVerifBuffer.getAllocation());
2351 
2352     const auto baseVerifData     = reinterpret_cast<const uint8_t *>(baseVerifBuffer.getAllocation().getHostPtr());
2353     const auto hostXferVerifData = reinterpret_cast<const uint8_t *>(hostXferVerifBuffer.getAllocation().getHostPtr());
2354 
2355     for (size_t i = 0; i < imageMemSizeSz; ++i)
2356     {
2357         if (baseVerifData[i] != hostXferVerifData[i])
2358         {
2359             std::ostringstream msg;
2360             msg << "Base image and host copy image data differs at byte " << i << ": 0x" << std::hex << std::setw(2)
2361                 << std::setfill('0') << static_cast<int>(baseVerifData[i]) << " vs 0x" << std::hex << std::setw(2)
2362                 << std::setfill('0') << static_cast<int>(hostXferVerifData[i]);
2363             TCU_FAIL(msg.str());
2364         }
2365     }
2366 
2367     return tcu::TestStatus::pass("Pass");
2368 }
2369 
2370 class IdenticalMemoryLayoutTestCase : public vkt::TestCase
2371 {
2372 public:
IdenticalMemoryLayoutTestCase(tcu::TestContext & context,const char * name,const vk::VkFormat format,const vk::VkImageTiling tiling)2373     IdenticalMemoryLayoutTestCase(tcu::TestContext &context, const char *name, const vk::VkFormat format,
2374                                   const vk::VkImageTiling tiling)
2375         : TestCase(context, name)
2376         , m_format(format)
2377         , m_tiling(tiling)
2378     {
2379     }
2380 
2381 private:
createInstance(vkt::Context & context) const2382     vkt::TestInstance *createInstance(vkt::Context &context) const
2383     {
2384         return new IdenticalMemoryLayoutTestInstance(context, m_format, m_tiling);
2385     }
2386     void checkSupport(vkt::Context &context) const;
2387 
2388     const vk::VkFormat m_format;
2389     const vk::VkImageTiling m_tiling;
2390 };
2391 
checkSupport(vkt::Context & context) const2392 void IdenticalMemoryLayoutTestCase::checkSupport(vkt::Context &context) const
2393 {
2394     context.requireDeviceFunctionality("VK_EXT_host_image_copy");
2395 
2396     const InstanceInterface &vki          = context.getInstanceInterface();
2397     VkFormatProperties3 formatProperties3 = initVulkanStructure();
2398     VkFormatProperties2 formatProperties2 = initVulkanStructure(&formatProperties3);
2399     const auto requiredFeatures =
2400         (VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT);
2401     const auto imageUsage = (VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2402 
2403     vki.getPhysicalDeviceFormatProperties2(context.getPhysicalDevice(), m_format, &formatProperties2);
2404 
2405     if (m_tiling == VK_IMAGE_TILING_OPTIMAL &&
2406         (formatProperties3.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
2407         TCU_THROW(NotSupportedError, "Required format feature not supported for optimal tiling.");
2408 
2409     if (m_tiling == VK_IMAGE_TILING_LINEAR &&
2410         (formatProperties3.linearTilingFeatures & requiredFeatures) != requiredFeatures)
2411         TCU_THROW(NotSupportedError, "Required format feature not supported for linear tiling.");
2412 
2413     VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
2414         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType;
2415         nullptr,                                               // const void* pNext;
2416         m_format,                                              // VkFormat format;
2417         VK_IMAGE_TYPE_2D,                                      // VkImageType type;
2418         m_tiling,                                              // VkImageTiling tiling;
2419         imageUsage,                                            // VkImageUsageFlags usage;
2420         0u,                                                    // VkImageCreateFlags flags;
2421     };
2422 
2423     VkHostImageCopyDevicePerformanceQueryEXT hostImageCopyDevicePerformanceQuery = initVulkanStructure();
2424     VkImageFormatProperties2 imageFormatProperties = initVulkanStructure(&hostImageCopyDevicePerformanceQuery);
2425 
2426     VkResult res = vki.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo,
2427                                                                &imageFormatProperties);
2428 
2429     if (res == VK_ERROR_FORMAT_NOT_SUPPORTED)
2430         TCU_THROW(NotSupportedError, "Format not supported");
2431 
2432     if (!hostImageCopyDevicePerformanceQuery.identicalMemoryLayout)
2433         TCU_THROW(NotSupportedError, "identicalMemoryLayout not supported for this format");
2434 }
2435 
2436 struct DepthStencilHICParams
2437 {
2438     VkFormat format;
2439     tcu::IVec2 extent;
2440 };
2441 
2442 class DepthStencilHostImageCopyInstance : public vkt::TestInstance
2443 {
2444 public:
DepthStencilHostImageCopyInstance(Context & context,const DepthStencilHICParams & params)2445     DepthStencilHostImageCopyInstance(Context &context, const DepthStencilHICParams &params)
2446         : vkt::TestInstance(context)
2447         , m_params(params)
2448     {
2449     }
~DepthStencilHostImageCopyInstance(void)2450     virtual ~DepthStencilHostImageCopyInstance(void)
2451     {
2452     }
2453 
2454     tcu::TestStatus iterate(void);
2455 
2456 protected:
2457     const DepthStencilHICParams m_params;
2458 };
2459 
2460 class DepthStencilHostImageCopyTest : public vkt::TestCase
2461 {
2462 public:
getGeometryDepth(void)2463     static float getGeometryDepth(void)
2464     {
2465         return 0.5f;
2466     }
getGeometryColor(void)2467     static tcu::Vec4 getGeometryColor(void)
2468     {
2469         return tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2470     }
getClearColor(void)2471     static tcu::Vec4 getClearColor(void)
2472     {
2473         return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2474     }
2475 
2476     // Tests require host image transfer, general transfer and depth/stencil usage.
getDepthStencilUsage(void)2477     static VkImageUsageFlags getDepthStencilUsage(void)
2478     {
2479         return (VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
2480                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
2481     }
2482 
getDepthStencilFormatFeatures(void)2483     static VkFormatFeatureFlags2 getDepthStencilFormatFeatures(void)
2484     {
2485         return (VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT |
2486                 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT);
2487     }
2488 
DepthStencilHostImageCopyTest(tcu::TestContext & testCtx,const std::string & name,const DepthStencilHICParams & params)2489     DepthStencilHostImageCopyTest(tcu::TestContext &testCtx, const std::string &name,
2490                                   const DepthStencilHICParams &params)
2491         : vkt::TestCase(testCtx, name)
2492         , m_params(params)
2493     {
2494     }
~DepthStencilHostImageCopyTest(void)2495     virtual ~DepthStencilHostImageCopyTest(void)
2496     {
2497     }
2498 
2499     void initPrograms(vk::SourceCollections &programCollection) const;
createInstance(Context & context) const2500     TestInstance *createInstance(Context &context) const
2501     {
2502         return new DepthStencilHostImageCopyInstance(context, m_params);
2503     }
2504     void checkSupport(Context &context) const;
2505 
2506 protected:
2507     const DepthStencilHICParams m_params;
2508 };
2509 
initPrograms(vk::SourceCollections & programCollection) const2510 void DepthStencilHostImageCopyTest::initPrograms(vk::SourceCollections &programCollection) const
2511 {
2512     const auto geometryDepth = getGeometryDepth();
2513     const auto geometryColor = getGeometryColor();
2514 
2515     std::ostringstream vert;
2516     vert << "#version 460\n"
2517          << "vec2 positions[3] = vec2[](\n"
2518          << "    vec2(-1.0, -1.0),\n"
2519          << "    vec2( 3.0, -1.0),\n"
2520          << "    vec2(-1.0, 3.0)\n"
2521          << ");\n"
2522          << "void main (void) {\n"
2523          << "    gl_Position = vec4(positions[gl_VertexIndex % 3], " << geometryDepth << ", 1.0);\n"
2524          << "}\n";
2525     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2526 
2527     std::ostringstream frag;
2528     frag << "#version 460\n"
2529          << "layout (location=0) out vec4 outColor;\n"
2530          << "void main (void) {\n"
2531          << "    outColor = vec4" << geometryColor << ";\n"
2532          << "}\n";
2533     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2534 }
2535 
checkSupport(Context & context) const2536 void DepthStencilHostImageCopyTest::checkSupport(Context &context) const
2537 {
2538     context.requireDeviceFunctionality("VK_EXT_host_image_copy");
2539 
2540     const auto &vki                       = context.getInstanceInterface();
2541     const auto physicalDevice             = context.getPhysicalDevice();
2542     VkFormatProperties3 formatProperties3 = initVulkanStructure();
2543     VkFormatProperties2 formatProperties2 = initVulkanStructure(&formatProperties3);
2544     const auto requiredFeatures           = getDepthStencilFormatFeatures();
2545     const auto imageUsage                 = getDepthStencilUsage();
2546 
2547     // Check format support.
2548     vki.getPhysicalDeviceFormatProperties2(physicalDevice, m_params.format, &formatProperties2);
2549 
2550     if ((formatProperties3.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
2551         TCU_THROW(NotSupportedError, "Required format features not supported for this format");
2552 
2553     // Check image usage support.
2554     const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
2555         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType;
2556         nullptr,                                               // const void* pNext;
2557         m_params.format,                                       // VkFormat format;
2558         VK_IMAGE_TYPE_2D,                                      // VkImageType type;
2559         VK_IMAGE_TILING_OPTIMAL,                               // VkImageTiling tiling;
2560         imageUsage,                                            // VkImageUsageFlags usage;
2561         0u,                                                    // VkImageCreateFlags flags;
2562     };
2563 
2564     VkImageFormatProperties2 imageFormatProperties = initVulkanStructure();
2565     const auto res =
2566         vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageFormatProperties);
2567 
2568     if (res == VK_ERROR_FORMAT_NOT_SUPPORTED)
2569         TCU_THROW(NotSupportedError, "Image usage not supported for this format");
2570 }
2571 
hostLayoutTransition(const DeviceInterface & vkd,const VkDevice device,const VkImage image,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImageSubresourceRange & imageSRR)2572 void hostLayoutTransition(const DeviceInterface &vkd, const VkDevice device, const VkImage image,
2573                           const VkImageLayout oldLayout, const VkImageLayout newLayout,
2574                           const VkImageSubresourceRange &imageSRR)
2575 {
2576     const VkHostImageLayoutTransitionInfoEXT toTransfer{
2577         VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT, // VkStructureType sType;
2578         nullptr,                                                 // const void* pNext;
2579         image,                                                   // VkImage image;
2580         oldLayout,                                               // VkImageLayout oldLayout;
2581         newLayout,                                               // VkImageLayout newLayout;
2582         imageSRR,                                                // VkImageSubresourceRange subresourceRange;
2583     };
2584     vkd.transitionImageLayoutEXT(device, 1u, &toTransfer);
2585 }
2586 
copyDSMemoryToImage(const DeviceInterface & vkd,const VkDevice device,const VkImage image,const VkImageLayout layout,const VkImageAspectFlagBits aspect,const void * pixelData,const VkExtent3D & extent)2587 void copyDSMemoryToImage(const DeviceInterface &vkd, const VkDevice device, const VkImage image,
2588                          const VkImageLayout layout, const VkImageAspectFlagBits aspect, const void *pixelData,
2589                          const VkExtent3D &extent)
2590 {
2591     const VkMemoryToImageCopyEXT copyRegion = {
2592         VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,     // VkStructureType sType;
2593         nullptr,                                        // const void* pNext;
2594         pixelData,                                      // const void* pHostPointer;
2595         0u,                                             // uint32_t memoryRowLength;
2596         0u,                                             // uint32_t memoryImageHeight;
2597         makeImageSubresourceLayers(aspect, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
2598         makeOffset3D(0, 0, 0),                          // VkOffset3D imageOffset;
2599         extent,                                         // VkExtent3D imageExtent;
2600     };
2601 
2602     const VkCopyMemoryToImageInfoEXT copyInfo = {
2603         VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT, // VkStructureType sType;
2604         nullptr,                                         // const void* pNext;
2605         0u,                                              // VkHostImageCopyFlagsEXT flags;
2606         image,                                           // VkImage dstImage;
2607         layout,                                          // VkImageLayout dstImageLayout;
2608         1u,                                              // uint32_t regionCount;
2609         &copyRegion,                                     // const VkMemoryToImageCopyEXT* pRegions;
2610     };
2611 
2612     vkd.copyMemoryToImageEXT(device, &copyInfo);
2613 }
2614 
copyDSImageToMemory(const DeviceInterface & vkd,const VkDevice device,const VkImage image,const VkImageLayout layout,const VkImageAspectFlagBits aspect,void * pixelData,const VkExtent3D & extent)2615 void copyDSImageToMemory(const DeviceInterface &vkd, const VkDevice device, const VkImage image,
2616                          const VkImageLayout layout, const VkImageAspectFlagBits aspect, void *pixelData,
2617                          const VkExtent3D &extent)
2618 {
2619     const VkImageToMemoryCopyEXT copyRegion = {
2620         VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,     // VkStructureType sType;
2621         nullptr,                                        // const void* pNext;
2622         pixelData,                                      // void* pHostPointer;
2623         0u,                                             // uint32_t memoryRowLength;
2624         0u,                                             // uint32_t memoryImageHeight;
2625         makeImageSubresourceLayers(aspect, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
2626         makeOffset3D(0, 0, 0),                          // VkOffset3D imageOffset;
2627         extent,                                         // VkExtent3D imageExtent;
2628     };
2629 
2630     const VkCopyImageToMemoryInfoEXT copyInfo = {
2631         VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT, // VkStructureType sType;
2632         nullptr,                                         // const void* pNext;
2633         0u,                                              // VkHostImageCopyFlagsEXT flags;
2634         image,                                           // VkImage srcImage;
2635         layout,                                          // VkImageLayout srcImageLayout;
2636         1u,                                              // uint32_t regionCount;
2637         &copyRegion,                                     // const VkImageToMemoryCopyEXT* pRegions;
2638     };
2639 
2640     vkd.copyImageToMemoryEXT(device, &copyInfo);
2641 }
2642 
iterate(void)2643 tcu::TestStatus DepthStencilHostImageCopyInstance::iterate(void)
2644 {
2645     const auto ctx         = m_context.getContextCommonData();
2646     const auto imageType   = VK_IMAGE_TYPE_2D;
2647     const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2648     const auto colorUsage  = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2649     const auto colorSRR    = makeDefaultImageSubresourceRange();
2650     const auto colorSRL    = makeDefaultImageSubresourceLayers();
2651     const auto fbExtent    = tcu::IVec3(m_params.extent.x(), m_params.extent.y(), 1);
2652     const auto vkExtent    = makeExtent3D(fbExtent);
2653     const auto tcuFormat   = mapVkFormat(m_params.format);
2654     const bool hasDepth    = tcu::hasDepthComponent(tcuFormat.order);
2655     const bool hasStencil  = tcu::hasStencilComponent(tcuFormat.order);
2656     const auto dsUsage     = DepthStencilHostImageCopyTest::getDepthStencilUsage();
2657     const auto dsAspects =
2658         ((hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) | (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : 0));
2659     const auto dsSRR     = makeImageSubresourceRange(dsAspects, 0u, 1u, 0u, 1u);
2660     const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
2661 
2662     const auto geometryDepth = DepthStencilHostImageCopyTest::getGeometryDepth();
2663     const auto geometryColor = DepthStencilHostImageCopyTest::getGeometryColor();
2664     const auto clearColor    = DepthStencilHostImageCopyTest::getClearColor();
2665 
2666     const auto depthFormat   = (hasDepth ? getDepthCopyFormat(m_params.format) : tcu::TextureFormat());
2667     const auto stencilFormat = (hasStencil ? getStencilCopyFormat(m_params.format) : tcu::TextureFormat());
2668 
2669     // Color buffer.
2670     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, colorFormat, colorUsage, imageType);
2671 
2672     // Depth/stencil image.
2673     const VkImageCreateInfo dsImageCreateInfo = {
2674         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2675         nullptr,                             // const void* pNext;
2676         0u,                                  // VkImageCreateFlags flags;
2677         imageType,                           // VkImageType imageType;
2678         m_params.format,                     // VkFormat format;
2679         vkExtent,                            // VkExtent3D extent;
2680         1u,                                  // uint32_t mipLevels;
2681         1u,                                  // uint32_t arrayLayers;
2682         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
2683         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
2684         dsUsage,                             // VkImageUsageFlags usage;
2685         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
2686         0u,                                  // uint32_t queueFamilyIndexCount;
2687         nullptr,                             // const uint32_t* pQueueFamilyIndices;
2688         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
2689     };
2690     ImageWithMemory dsImage(ctx.vkd, ctx.device, ctx.allocator, dsImageCreateInfo, MemoryRequirement::Any);
2691     const auto dsImageView =
2692         makeImageView(ctx.vkd, ctx.device, *dsImage, VK_IMAGE_VIEW_TYPE_2D, dsImageCreateInfo.format, dsSRR);
2693 
2694     tcu::TextureLevel origDepthLevel;
2695     tcu::TextureLevel origStencilLevel;
2696     tcu::PixelBufferAccess origDepthAccess;
2697     tcu::PixelBufferAccess origStencilAccess;
2698 
2699     const uint64_t randomSeed =
2700         ((static_cast<uint64_t>(vkExtent.width) << 48) | (static_cast<uint64_t>(vkExtent.height) << 32) |
2701          static_cast<uint64_t>(m_params.format));
2702     de::Random rnd(deUint64Hash(randomSeed));
2703 
2704     if (hasDepth)
2705     {
2706         // We will fill the depth buffer randomly with values that should not create precision problems.
2707         // Geometry depth should be 0.5 (see the vertex shader).
2708         origDepthLevel.setStorage(depthFormat, fbExtent.x(), fbExtent.y());
2709         origDepthAccess = origDepthLevel.getAccess();
2710 
2711         for (int y = 0; y < fbExtent.y(); ++y)
2712             for (int x = 0; x < fbExtent.x(); ++x)
2713             {
2714                 const bool pass = rnd.getBool();
2715                 // Generates values in the [0, 0.25] or [0.75, 1.0] ranges depending on "pass".
2716                 const auto depthOffset = (pass ? 0.0f : 0.75f);
2717                 origDepthAccess.setPixDepth(rnd.getFloat() * 0.25f + depthOffset, x, y);
2718             }
2719     }
2720 
2721     if (hasStencil)
2722     {
2723         // We will fill the stencil buffer randomly as well. In this case there are no precision issues, but we will reserve value
2724         // zero to be special-cased later. The stencil reference value will be 128 (see below).
2725         origStencilLevel.setStorage(stencilFormat, fbExtent.x(), fbExtent.y());
2726         origStencilAccess = origStencilLevel.getAccess();
2727 
2728         for (int y = 0; y < fbExtent.y(); ++y)
2729             for (int x = 0; x < fbExtent.x(); ++x)
2730                 origStencilAccess.setPixStencil(rnd.getInt(1, 255), x, y);
2731     }
2732 
2733     // Fill the depth/stencil buffer from the host and prepare it to be used.
2734     hostLayoutTransition(ctx.vkd, ctx.device, *dsImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, dsSRR);
2735 
2736     if (hasDepth)
2737     {
2738         copyDSMemoryToImage(ctx.vkd, ctx.device, *dsImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_DEPTH_BIT,
2739                             origDepthAccess.getDataPtr(), vkExtent);
2740     }
2741 
2742     if (hasStencil)
2743     {
2744         copyDSMemoryToImage(ctx.vkd, ctx.device, *dsImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_STENCIL_BIT,
2745                             origStencilAccess.getDataPtr(), vkExtent);
2746     }
2747 
2748     // Render pass.
2749     const std::vector<VkAttachmentDescription> attachmentDescriptions{
2750         // Color attachment description.
2751         makeAttachmentDescription(0u, colorFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
2752                                   VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
2753                                   VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
2754                                   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL),
2755 
2756         // Depth/stencil attachment description.
2757         makeAttachmentDescription(0u, m_params.format, VK_SAMPLE_COUNT_1_BIT,
2758                                   (hasDepth ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
2759                                   (hasDepth ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),
2760                                   (hasStencil ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
2761                                   (hasStencil ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE),
2762                                   VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL),
2763     };
2764 
2765     const auto colorAttRef = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2766     const auto dsAttRef    = makeAttachmentReference(1u, VK_IMAGE_LAYOUT_GENERAL);
2767     const auto subpass =
2768         makeSubpassDescription(0u, bindPoint, 0u, nullptr, 1u, &colorAttRef, nullptr, &dsAttRef, 0u, nullptr);
2769 
2770     const VkRenderPassCreateInfo renderPassCreateInfo = {
2771         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
2772         nullptr,                                   // const void* pNext;
2773         0u,                                        // VkRenderPassCreateFlags flags;
2774         de::sizeU32(attachmentDescriptions),       // uint32_t attachmentCount;
2775         de::dataOrNull(attachmentDescriptions),    // const VkAttachmentDescription* pAttachments;
2776         1u,                                        // uint32_t subpassCount;
2777         &subpass,                                  // const VkSubpassDescription* pSubpasses;
2778         0u,                                        // uint32_t dependencyCount;
2779         nullptr,                                   // const VkSubpassDependency* pDependencies;
2780     };
2781     const auto renderPass = createRenderPass(ctx.vkd, ctx.device, &renderPassCreateInfo);
2782 
2783     // Viewports and scissors.
2784     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
2785     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
2786 
2787     // Framebuffer.
2788     const std::vector<VkImageView> fbViews{colorBuffer.getImageView(), *dsImageView};
2789     const auto framebuffer = makeFramebuffer(ctx.vkd, ctx.device, *renderPass, de::sizeU32(fbViews),
2790                                              de::dataOrNull(fbViews), vkExtent.width, vkExtent.height);
2791 
2792     // Shader modules.
2793     const auto &binaries  = m_context.getBinaryCollection();
2794     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
2795     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
2796 
2797     // Empty vertex input state.
2798     const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2799 
2800     // Depth/stencil state.
2801     const auto stencilRef = 128;
2802     const auto stencilOp  = makeStencilOpState(VK_STENCIL_OP_ZERO, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_ZERO,
2803                                                VK_COMPARE_OP_GREATER, 0xFFu, 0xFFu, static_cast<uint32_t>(stencilRef));
2804 
2805     const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
2806         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
2807         nullptr,                                                    // const void* pNext;
2808         0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
2809         makeVkBool(hasDepth),                                       // VkBool32 depthTestEnable;
2810         makeVkBool(hasDepth),                                       // VkBool32 depthWriteEnable;
2811         VK_COMPARE_OP_GREATER,                                      // VkCompareOp depthCompareOp;
2812         VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
2813         makeVkBool(hasStencil),                                     // VkBool32 stencilTestEnable;
2814         stencilOp,                                                  // VkStencilOpState front;
2815         stencilOp,                                                  // VkStencilOpState back;
2816         0.0f,                                                       // float minDepthBounds;
2817         0.0f,                                                       // float maxDepthBounds;
2818     };
2819 
2820     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
2821     const auto pipeline       = makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout, *vertModule, VK_NULL_HANDLE,
2822                                                      VK_NULL_HANDLE, VK_NULL_HANDLE, *fragModule, *renderPass, viewports,
2823                                                      scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u, &vertexInputState,
2824                                                      nullptr, nullptr, &depthStencilState);
2825 
2826     // Run pipeline.
2827     const CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
2828     const auto cmdBuffer = cmd.cmdBuffer.get();
2829 
2830     beginCommandBuffer(ctx.vkd, cmdBuffer);
2831 
2832     // Rendering.
2833     beginRenderPass(ctx.vkd, cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), clearColor);
2834     ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline);
2835     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
2836     endRenderPass(ctx.vkd, cmdBuffer);
2837 
2838     // Depth/stencil buffer sync to the host layout change and host image copy operations that will follow.
2839     const auto dsBarrier = makeMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
2840                                              (VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT));
2841 
2842     // Color buffer sync to the transfer operation that follows.
2843     const auto colorBarrier = makeImageMemoryBarrier(
2844         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2845         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.getImage(), colorSRR);
2846 
2847     ctx.vkd.cmdPipelineBarrier(cmdBuffer,
2848                                (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
2849                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT),
2850                                (VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT), 0u, 1u, &dsBarrier, 0u,
2851                                nullptr, 1u, &colorBarrier);
2852 
2853     // Copy color buffer to its verification buffer.
2854     const auto colorCopyRegion = makeBufferImageCopy(vkExtent, colorSRL);
2855     ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2856                                  colorBuffer.getBuffer(), 1u, &colorCopyRegion);
2857 
2858     // Sync color copy with host reads.
2859     const auto transferToHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2860     cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2861                              &transferToHostBarrier);
2862 
2863     endCommandBuffer(ctx.vkd, cmdBuffer);
2864     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2865 
2866     // Invalidate color verification buffer allocation and create an access to it.
2867     auto &colorBufferAlloc     = colorBuffer.getBufferAllocation();
2868     const auto colorBufferData = colorBufferAlloc.getHostPtr();
2869     const auto colorAccess     = tcu::ConstPixelBufferAccess(mapVkFormat(colorFormat), fbExtent, colorBufferData);
2870     invalidateAlloc(ctx.vkd, ctx.device, colorBufferAlloc);
2871 
2872     // Transfer depth buffer (via host image copy) to a couple of texture levels for verification after use.
2873     tcu::TextureLevel finalDepthLevel;
2874     tcu::TextureLevel finalStencilLevel;
2875     tcu::PixelBufferAccess finalDepthAccess;
2876     tcu::PixelBufferAccess finalStencilAccess;
2877 
2878     if (hasDepth)
2879     {
2880         finalDepthLevel.setStorage(depthFormat, fbExtent.x(), fbExtent.y());
2881         finalDepthAccess = finalDepthLevel.getAccess();
2882 
2883         copyDSImageToMemory(ctx.vkd, ctx.device, *dsImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_DEPTH_BIT,
2884                             finalDepthAccess.getDataPtr(), vkExtent);
2885     }
2886 
2887     if (hasStencil)
2888     {
2889         finalStencilLevel.setStorage(stencilFormat, fbExtent.x(), fbExtent.y());
2890         finalStencilAccess = finalStencilLevel.getAccess();
2891 
2892         copyDSImageToMemory(ctx.vkd, ctx.device, *dsImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_STENCIL_BIT,
2893                             finalStencilAccess.getDataPtr(), vkExtent);
2894     }
2895 
2896     // Verify color buffer and depth/stencil values.
2897     tcu::TextureLevel colorErrorMask(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
2898                                      fbExtent.x(), fbExtent.y());
2899     tcu::TextureLevel depthErrorMask(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
2900                                      fbExtent.x(), fbExtent.y());
2901     tcu::TextureLevel stencilErrorMask(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
2902                                        fbExtent.x(), fbExtent.y());
2903 
2904     auto colorErrorAccess   = colorErrorMask.getAccess();
2905     auto depthErrorAccess   = depthErrorMask.getAccess();
2906     auto stencilErrorAccess = stencilErrorMask.getAccess();
2907 
2908     bool allColorOK   = true;
2909     bool allDepthOK   = true;
2910     bool allStencilOK = true;
2911     const auto green  = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2912     const auto red    = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2913 
2914     // Calculate depth threshold to be used when the expected depth value is the geometry depth.
2915     float depthTestPassThreshold = -1000.0f;
2916     const auto depthBits         = (hasDepth ? tcu::getTextureFormatBitDepth(tcuFormat).x() : 0);
2917     switch (depthBits)
2918     {
2919     case 0:
2920         // No depth aspect.
2921         break;
2922     case 16:
2923     case 24:
2924         depthTestPassThreshold = 1.0f / static_cast<float>((1u << depthBits) - 1u);
2925         break;
2926     case 32:
2927         // 0 is an acceptable threshold here because the geometry depth value is exactly representable as a float.
2928         depthTestPassThreshold = 0.0f;
2929         break;
2930     default:
2931         DE_ASSERT(false);
2932         break;
2933     }
2934 
2935     for (int y = 0; y < fbExtent.y(); ++y)
2936         for (int x = 0; x < fbExtent.x(); ++x)
2937         {
2938             const float origDepth      = (hasDepth ? origDepthAccess.getPixDepth(x, y) : -1000.0f);
2939             const int origStencil      = (hasStencil ? origStencilAccess.getPixStencil(x, y) : -1);
2940             const bool depthTestPass   = (hasDepth ? (geometryDepth > origDepth) : true);  // VK_COMPARE_OP_GREATER
2941             const bool stencilTestPass = (hasStencil ? (stencilRef > origStencil) : true); // VK_COMPARE_OP_GREATER
2942             const bool bothTestsPass   = (depthTestPass && stencilTestPass);
2943 
2944             const auto expectedColor  = (bothTestsPass ? geometryColor : clearColor);
2945             const float expectedDepth = (bothTestsPass ? geometryDepth : origDepth);
2946             const int expectedStencil = (bothTestsPass ? origStencil /*VK_STENCIL_OP_KEEP*/ : 0 /*VK_STENCIL_OP_ZERO*/);
2947 
2948             const auto resultColor   = colorAccess.getPixel(x, y);
2949             const auto resultDepth   = (hasDepth ? finalDepthAccess.getPixDepth(x, y) : -1000.0f);
2950             const auto resultStencil = (hasStencil ? finalStencilAccess.getPixStencil(x, y) : -1);
2951 
2952             const bool colorOK = (resultColor == expectedColor);
2953             const bool depthOK =
2954                 (hasDepth ? (depthTestPass ?
2955                                  (std::abs(resultDepth - expectedDepth) <= depthTestPassThreshold) // Geometry depth.
2956                                  :
2957                                  (expectedDepth == resultDepth)) // Unmodified depth, expect the exact same value back.
2958                             :
2959                             true);
2960             const bool stencilOK = (hasStencil ? (expectedStencil == resultStencil) : true);
2961 
2962             colorErrorAccess.setPixel((colorOK ? green : red), x, y);
2963             depthErrorAccess.setPixel((depthOK ? green : red), x, y);
2964             stencilErrorAccess.setPixel((stencilOK ? green : red), x, y);
2965 
2966             allColorOK   = (allColorOK && colorOK);
2967             allDepthOK   = (allDepthOK && depthOK);
2968             allStencilOK = (allStencilOK && stencilOK);
2969         }
2970 
2971     auto &log = m_context.getTestContext().getLog();
2972 
2973     if (!allColorOK)
2974     {
2975         log << tcu::TestLog::ImageSet("ColorComparison", "") << tcu::TestLog::Image("ColorResult", "", colorAccess)
2976             << tcu::TestLog::Image("ColorErrorMask", "", colorErrorAccess) << tcu::TestLog::EndImageSet;
2977     }
2978 
2979     if (!allDepthOK)
2980     {
2981         log << tcu::TestLog::ImageSet("DepthComparison", "")
2982             << tcu::TestLog::Image("DepthErrorMask", "", depthErrorAccess) << tcu::TestLog::EndImageSet;
2983     }
2984 
2985     if (!allStencilOK)
2986     {
2987         log << tcu::TestLog::ImageSet("StencilComparison", "")
2988             << tcu::TestLog::Image("StencilErrorMask", "", stencilErrorAccess) << tcu::TestLog::EndImageSet;
2989     }
2990 
2991     if (!(allColorOK && allDepthOK && allStencilOK))
2992         return tcu::TestStatus::fail("Unexpected values in color, depth or stencil buffers -- check log for details");
2993     return tcu::TestStatus::pass("Pass");
2994 }
2995 
testGenerator(tcu::TestCaseGroup * group)2996 void testGenerator(tcu::TestCaseGroup *group)
2997 {
2998     constexpr struct CopyTest
2999     {
3000         bool hostTransferLayout;
3001         bool copyMemoryToImage;
3002         const char *name;
3003     } copyTests[] = {
3004         // Host copy and transfer
3005         {true, true, "host_transfer_copy_general"},
3006         // Host transfer
3007         {true, false, "host_transfer"},
3008         // Host copy
3009         {false, true, "host_copy"},
3010     };
3011 
3012     constexpr struct CopyImageToMemory
3013     {
3014         bool hostCopyImageToMemory;
3015         const char *name;
3016     } copyImageToMemoryTests[] = {
3017         // Copy from image to memory on host
3018         {true, "host_image_to_memory_copy"},
3019         // Copy from image to memory on gpu
3020         {false, "image_to_memory_copy"},
3021     };
3022 
3023     constexpr struct TransitionTest
3024     {
3025         bool host;
3026         const char *name;
3027     } transitionTests[] = {
3028         // Transition using vkTransitionImageLayoutEXT
3029         {true, "host_transition"},
3030         // Transition using a pipeline barrier
3031         {false, "barrier_transition"},
3032     };
3033 
3034     const struct FlagsTest
3035     {
3036         bool memcpy;
3037         const char *name;
3038     } flagsTests[] = {
3039         // Copy with no flags
3040         {false, "none"},
3041         // Copy with VK_HOST_IMAGE_COPY_MEMCPY_EXT flag
3042         {true, "memcpy"},
3043     };
3044 
3045     const struct Tiling
3046     {
3047         vk::VkImageTiling tiling;
3048         const char *name;
3049     } tilingTests[] = {
3050         {vk::VK_IMAGE_TILING_LINEAR, "linear"},
3051         {vk::VK_IMAGE_TILING_OPTIMAL, "optimal"},
3052     };
3053 
3054     const struct ImageFormatsAndCommand
3055     {
3056         Command command;
3057         vk::VkFormat sampled;
3058         vk::VkFormat output;
3059     } formatsAndCommands[] = {
3060         {DRAW, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_FORMAT_R8G8B8A8_UNORM},
3061         {DRAW, vk::VK_FORMAT_R8G8_UNORM, vk::VK_FORMAT_R8G8_UNORM},
3062         {DRAW, vk::VK_FORMAT_R32G32B32A32_SFLOAT, vk::VK_FORMAT_R32G32B32A32_SFLOAT},
3063         {DRAW, vk::VK_FORMAT_R8_UNORM, vk::VK_FORMAT_R8_UNORM},
3064         {DRAW, vk::VK_FORMAT_R32G32_SFLOAT, vk::VK_FORMAT_R32G32_SFLOAT},
3065         {DRAW, vk::VK_FORMAT_R16_UNORM, vk::VK_FORMAT_R16_UNORM},
3066         {DRAW, vk::VK_FORMAT_D16_UNORM, vk::VK_FORMAT_R16_UNORM},
3067         {DRAW, vk::VK_FORMAT_D32_SFLOAT, vk::VK_FORMAT_R32_SFLOAT},
3068         {DRAW, vk::VK_FORMAT_BC7_UNORM_BLOCK, vk::VK_FORMAT_R8G8B8A8_UNORM},
3069         {DRAW, vk::VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, vk::VK_FORMAT_R8G8B8A8_UNORM},
3070         {DRAW, vk::VK_FORMAT_ASTC_4x4_UNORM_BLOCK, vk::VK_FORMAT_R8G8B8A8_UNORM},
3071         {DISPATCH, vk::VK_FORMAT_R10X6_UNORM_PACK16, vk::VK_FORMAT_R10X6_UNORM_PACK16},
3072         {DISPATCH, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_FORMAT_R8G8B8A8_UNORM},
3073         {DISPATCH, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_FORMAT_R8G8B8A8_UINT},
3074     };
3075 
3076     const std::set<vk::VkFormat> restrictedCombinationsFmt{
3077         vk::VK_FORMAT_R8G8_UNORM,
3078         vk::VK_FORMAT_R8_UNORM,
3079         vk::VK_FORMAT_R32G32_SFLOAT,
3080     };
3081 
3082     const struct ImageSizes
3083     {
3084         vk::VkExtent3D size;
3085         const char *name;
3086     } imageSizes[] = {
3087         {makeExtent3D(16u, 16u, 1u), "16x16"},
3088         {makeExtent3D(32u, 28u, 1u), "32x28"},
3089         {makeExtent3D(53u, 61u, 1u), "53x61"},
3090     };
3091 
3092     constexpr struct ImageLayoutTest
3093     {
3094         vk::VkImageLayout srcLayout;
3095         vk::VkImageLayout dstLayout;
3096         const char *name;
3097     } imageLayoutTests[] = {
3098         {vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, "general_general"},
3099         {vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
3100          "transfer_src_transfer_dst"},
3101     };
3102 
3103     constexpr struct IntermediateImageLayoutTest
3104     {
3105         vk::VkImageLayout layout;
3106         const char *name;
3107     } intermediateImageLayoutTests[] = {
3108         {vk::VK_IMAGE_LAYOUT_GENERAL, "general"},
3109         {vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "color_attachment_optimal"},
3110         {vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "depth_stencil_attachment_optimal"},
3111         {vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "depth_stencil_read_only_optimal"},
3112         {vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "shader_read_only_optimal"},
3113         {vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "transfer_src_optimal"},
3114         {vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "transfer_dst_optimal"},
3115     };
3116 
3117     constexpr struct MipLevelRegionCountPaddingTest
3118     {
3119         uint32_t mipLevel;
3120         uint32_t regionsCount;
3121         uint32_t padding;
3122         const char *name;
3123         const char *desc;
3124     } mipLevelRegionCountPaddingTests[] = {
3125         {0u, 1u, 0u, "0_1_0", ""}, {1u, 1u, 0u, "1_1_0", ""},     {4u, 1u, 0u, "4_1_0", ""},
3126         {0u, 4u, 4u, "0_4_4", ""}, {0u, 16u, 64u, "0_16_64", ""},
3127     };
3128 
3129     tcu::TestContext &testCtx = group->getTestContext();
3130 
3131     for (const auto &formatAndCommand : formatsAndCommands)
3132     {
3133         std::string formatName = formatAndCommand.command == DRAW ? "draw" : "dispatch";
3134         formatName +=
3135             "_" + getFormatShortString(formatAndCommand.output) + "_" + getFormatShortString(formatAndCommand.sampled);
3136         tcu::TestCaseGroup *const formatGroup = new tcu::TestCaseGroup(testCtx, formatName.c_str());
3137 
3138         bool colorFormat = isCompressedFormat(formatAndCommand.sampled) ||
3139                            !(tcu::hasDepthComponent(mapVkFormat(formatAndCommand.sampled).order) ||
3140                              tcu::hasDepthComponent(mapVkFormat(formatAndCommand.sampled).order));
3141 
3142         bool dynamicRenderingBase = true;
3143         bool sparseImageBase      = true;
3144 
3145         for (const auto &copy : copyTests)
3146         {
3147             // Anitalias the config stride!
3148             dynamicRenderingBase  = !dynamicRenderingBase;
3149             bool dynamicRendering = dynamicRenderingBase;
3150 
3151             tcu::TestCaseGroup *const copyTestGroup = new tcu::TestCaseGroup(testCtx, copy.name);
3152             for (const auto &imageToMemory : copyImageToMemoryTests)
3153             {
3154                 tcu::TestCaseGroup *const imageToMemoryGroup = new tcu::TestCaseGroup(testCtx, imageToMemory.name);
3155                 for (const auto &transition : transitionTests)
3156                 {
3157                     tcu::TestCaseGroup *const transitionGroup = new tcu::TestCaseGroup(testCtx, transition.name);
3158                     for (const auto &flags : flagsTests)
3159                     {
3160                         tcu::TestCaseGroup *const flagsGroup = new tcu::TestCaseGroup(testCtx, flags.name);
3161                         for (const auto &layouts : imageLayoutTests)
3162                         {
3163                             tcu::TestCaseGroup *const layoutsGroup = new tcu::TestCaseGroup(testCtx, layouts.name);
3164                             for (const auto &intermediateLayout : intermediateImageLayoutTests)
3165                             {
3166                                 if (colorFormat &&
3167                                     (intermediateLayout.layout ==
3168                                          vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
3169                                      intermediateLayout.layout == vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL))
3170                                     continue;
3171                                 else if (!colorFormat &&
3172                                          intermediateLayout.layout == vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
3173                                     continue;
3174 
3175                                 tcu::TestCaseGroup *const intermediateLayoutGroup =
3176                                     new tcu::TestCaseGroup(testCtx, intermediateLayout.name);
3177                                 for (const auto &tiling : tilingTests)
3178                                 {
3179                                     tcu::TestCaseGroup *const tilingGroup =
3180                                         new tcu::TestCaseGroup(testCtx, tiling.name);
3181                                     for (const auto &mipLevelRegionCountPaddingTest : mipLevelRegionCountPaddingTests)
3182                                     {
3183                                         // We are alternating the sparseImage flag here, make sure that count is not even, otherwise this has to be moved to a different loop
3184                                         static_assert(DE_LENGTH_OF_ARRAY(mipLevelRegionCountPaddingTests) % 2 != 0,
3185                                                       "Variation count is not odd");
3186                                         sparseImageBase  = !sparseImageBase;
3187                                         bool sparseImage = sparseImageBase;
3188 
3189                                         tcu::TestCaseGroup *const mipLevelRegionCountPaddingGroup =
3190                                             new tcu::TestCaseGroup(testCtx, mipLevelRegionCountPaddingTest.name);
3191                                         for (const auto &size : imageSizes)
3192                                         {
3193                                             // Alternate every test
3194                                             dynamicRendering = !dynamicRendering;
3195                                             sparseImage      = !sparseImage;
3196 
3197                                             if (sparseImage && isCompressedFormat(formatAndCommand.sampled))
3198                                                 continue;
3199 
3200                                             // These formats were added later, with restricted combinations considered interesting.
3201                                             if (restrictedCombinationsFmt.find(formatAndCommand.sampled) !=
3202                                                 restrictedCombinationsFmt.end())
3203                                             {
3204                                                 // Layouts are not that important.
3205                                                 if (!transition.host)
3206                                                     continue;
3207                                                 if (layouts.srcLayout == VK_IMAGE_LAYOUT_GENERAL)
3208                                                     continue;
3209                                                 if (intermediateLayout.layout != VK_IMAGE_LAYOUT_GENERAL)
3210                                                     continue;
3211 
3212                                                 // Linear tiling covered by R16.
3213                                                 if (tiling.tiling != VK_IMAGE_TILING_OPTIMAL)
3214                                                     continue;
3215 
3216                                                 // Mip levels covered by other formats.
3217                                                 if (mipLevelRegionCountPaddingTest.mipLevel != 0u ||
3218                                                     mipLevelRegionCountPaddingTest.regionsCount != 1u ||
3219                                                     mipLevelRegionCountPaddingTest.padding != 0u)
3220                                                 {
3221                                                     continue;
3222                                                 }
3223                                             }
3224 
3225                                             const TestParameters parameters = {
3226                                                 copy.copyMemoryToImage, // bool                copyMemoryToImage
3227                                                 imageToMemory
3228                                                     .hostCopyImageToMemory, // bool                hostCopyImageToMemory
3229                                                 copy.hostTransferLayout,    // bool                hostTransferLayout
3230                                                 transition.host,  // bool                outputImageHostTransition
3231                                                 flags.memcpy,     // bool                memcpyFlag
3232                                                 dynamicRendering, // bool                dynamicRendering
3233                                                 formatAndCommand.command,  // Command            command
3234                                                 formatAndCommand.sampled,  // VkFormat            imageSampledFormat
3235                                                 layouts.srcLayout,         // VkImageLayout    srcLayout
3236                                                 layouts.dstLayout,         // VkImageLayout    dstLayout
3237                                                 intermediateLayout.layout, // VkImageLayout    intermediateLayout
3238                                                 tiling.tiling,             // VkImageTiling sampledTiling;
3239                                                 formatAndCommand.output,   // VkFormat            imageOutputFormat
3240                                                 size.size,                 // VkExtent3D        imageSize
3241                                                 sparseImage,               // bool                sparse
3242                                                 mipLevelRegionCountPaddingTest.mipLevel, // uint32_t            mipLevel
3243                                                 mipLevelRegionCountPaddingTest
3244                                                     .regionsCount, // uint32_t            regionsCount
3245                                                 mipLevelRegionCountPaddingTest.padding // uint32_t            padding
3246                                             };
3247 
3248                                             mipLevelRegionCountPaddingGroup->addChild(
3249                                                 new HostImageCopyTestCase(testCtx, size.name, parameters));
3250                                         }
3251                                         tilingGroup->addChild(mipLevelRegionCountPaddingGroup);
3252                                     }
3253                                     intermediateLayoutGroup->addChild(tilingGroup);
3254                                 }
3255                                 layoutsGroup->addChild(intermediateLayoutGroup);
3256                             }
3257                             flagsGroup->addChild(layoutsGroup);
3258                         }
3259                         transitionGroup->addChild(flagsGroup);
3260                     }
3261                     imageToMemoryGroup->addChild(transitionGroup);
3262                 }
3263                 copyTestGroup->addChild(imageToMemoryGroup);
3264             }
3265             formatGroup->addChild(copyTestGroup);
3266         }
3267         group->addChild(formatGroup);
3268     }
3269 
3270     {
3271         using FormatPair = std::pair<VkFormat, VkFormat>; // .first = sampled, .second = output
3272 
3273         const std::vector<FormatPair> formatCases{
3274             std::make_pair(VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM),
3275             std::make_pair(VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8_UNORM),
3276             std::make_pair(VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT),
3277             std::make_pair(VK_FORMAT_D32_SFLOAT, VK_FORMAT_R32_SFLOAT),
3278             std::make_pair(VK_FORMAT_R10X6_UNORM_PACK16, VK_FORMAT_R10X6_UNORM_PACK16),
3279         };
3280 
3281         const std::vector<VkExtent3D> extentCases{
3282             makeExtent3D(128u, 128u, 1u),
3283             makeExtent3D(512u, 512u, 1u),
3284             makeExtent3D(4096u, 4096u, 1u),
3285         };
3286 
3287         de::MovePtr<tcu::TestCaseGroup> largeImages(new tcu::TestCaseGroup(testCtx, "large_images"));
3288         for (const auto &format : formatCases)
3289         {
3290             const auto &sampledFormat = format.first;
3291             const auto &outputFormat  = format.second;
3292 
3293             for (const auto &extent : extentCases)
3294             {
3295                 const TestParameters parameters = {
3296                     true,                    // bool          copyMemoryToImage
3297                     true,                    // bool          hostCopyImageToMemory
3298                     true,                    // bool          hostTransferLayout
3299                     true,                    // bool          outputImageHostTransition
3300                     false,                   // bool          memcpyFlag
3301                     false,                   // bool          dynamicRendering
3302                     DRAW,                    // Command       command
3303                     sampledFormat,           // VkFormat      imageSampledFormat
3304                     VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout srcLayout
3305                     VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout dstLayout
3306                     VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout intermediateLayout
3307                     VK_IMAGE_TILING_OPTIMAL, // VkImageTiling sampledTiling;
3308                     outputFormat,            // VkFormat      imageOutputFormat
3309                     extent,                  // VkExtent3D    imageSize
3310                     false,                   // bool          sparse
3311                     0u,                      // uint32_t      mipLevel
3312                     1u,                      // uint32_t      regionsCount
3313                     0u,                      // uint32_t      padding
3314                 };
3315 
3316                 const std::string testName = getFormatShortString(sampledFormat) + "_" + std::to_string(extent.height) +
3317                                              "_" + std::to_string(extent.height);
3318                 largeImages->addChild(new HostImageCopyTestCase(testCtx, testName.c_str(), parameters));
3319             }
3320         }
3321 
3322         group->addChild(largeImages.release());
3323     }
3324 
3325     const struct PreinitializedFormats
3326     {
3327         vk::VkFormat format;
3328     } preinitializedFormats[] = {
3329         {vk::VK_FORMAT_R8G8B8A8_UNORM}, {vk::VK_FORMAT_R32G32B32A32_SFLOAT}, {vk::VK_FORMAT_R16_UNORM},
3330         {vk::VK_FORMAT_R16G16_UINT},    {vk::VK_FORMAT_B8G8R8A8_SINT},       {vk::VK_FORMAT_R16_SFLOAT},
3331     };
3332 
3333     const struct PreinitializedTiling
3334     {
3335         vk::VkImageTiling tiling;
3336         const char *name;
3337     } preinitializedTilingTests[] = {
3338         {vk::VK_IMAGE_TILING_LINEAR, "linear"},
3339         {vk::VK_IMAGE_TILING_OPTIMAL, "optimal"},
3340         {vk::VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, "drm_format_modifier"},
3341     };
3342 
3343     constexpr struct PreinitializedImageLayoutTest
3344     {
3345         vk::VkImageLayout layout;
3346         const char *name;
3347     } preinitializedImageLayoutTests[] = {
3348         {vk::VK_IMAGE_LAYOUT_GENERAL, "general"},
3349         {vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, "color_attachment_optimal"},
3350         {vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, "depth_stencil_attachment_optimal"},
3351         {vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, "depth_stencil_read_only_optimal"},
3352         {vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, "shader_read_only_optimal"},
3353         {vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, "transfer_src_optimal"},
3354         {vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, "transfer_dst_optimal"},
3355         {vk::VK_IMAGE_LAYOUT_PREINITIALIZED, "preinitialized"},
3356         {vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, "present_src"},
3357         {vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, "depth_read_only_stencil_attachment_optimal"},
3358         {vk::VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, "depth_attachment_stencil_read_only_optimal"},
3359         {vk::VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, "depth_read_only_optimal"},
3360         {vk::VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, "stencil_attachment_optimal"},
3361         {vk::VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, "stencil_read_only_optimal"},
3362         {vk::VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, "read_only_optimal"},
3363         {vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, "attachment_optimal"},
3364         {vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, "attachment_feedback_loop_optimal"},
3365     };
3366 
3367     constexpr struct ImageToImageTest
3368     {
3369         bool imageToImageCopy;
3370         bool memcpy;
3371         const char *name;
3372     } imageToImageCopyTests[] = {
3373         {true, false, "image_to_image_copy"},
3374         {true, true, "image_to_image_memcpy"},
3375         {false, false, "preinitialized"},
3376     };
3377 
3378     constexpr struct ImageSizeTest
3379     {
3380         vk::VkExtent3D size;
3381         uint32_t layerCount;
3382         const char *name;
3383     } imageSizeTests[] = {
3384         {{32, 32, 1}, 1, "32x32x1_1"},
3385         {{32, 32, 1}, 2, "32x32x1_2"},
3386         {{51, 63, 1}, 1, "51x63x1_1"},
3387         {{24, 24, 4}, 1, "24x24x4_4"},
3388     };
3389 
3390     constexpr struct OffsetTest
3391     {
3392         uint32_t offset;
3393         const char *name;
3394     } offsetTests[] = {
3395         // No offset
3396         {0u, "0"},
3397         // Offset 64
3398         {64u, "64"},
3399     };
3400 
3401     for (const auto &tiling : preinitializedTilingTests)
3402     {
3403         tcu::TestCaseGroup *const tilingGroup = new tcu::TestCaseGroup(testCtx, tiling.name);
3404         for (const auto &imageToImage : imageToImageCopyTests)
3405         {
3406             tcu::TestCaseGroup *const imageToImageCopyGroup = new tcu::TestCaseGroup(testCtx, imageToImage.name);
3407             for (const auto &srcLayout : preinitializedImageLayoutTests)
3408             {
3409                 tcu::TestCaseGroup *const srcLayoutGroup = new tcu::TestCaseGroup(testCtx, srcLayout.name);
3410                 for (const auto &dstLayout : preinitializedImageLayoutTests)
3411                 {
3412                     tcu::TestCaseGroup *const dstLayoutGroup = new tcu::TestCaseGroup(testCtx, dstLayout.name);
3413                     for (const auto &size : imageSizeTests)
3414                     {
3415                         tcu::TestCaseGroup *const sizeGroup = new tcu::TestCaseGroup(testCtx, size.name);
3416                         for (const auto &offset : offsetTests)
3417                         {
3418                             tcu::TestCaseGroup *const offsetGroup = new tcu::TestCaseGroup(testCtx, offset.name);
3419                             for (const auto &format : preinitializedFormats)
3420                             {
3421                                 const auto formatName = getFormatShortString(format.format);
3422                                 offsetGroup->addChild(new PreinitializedTestCase(
3423                                     testCtx, formatName.c_str(), format.format, srcLayout.layout, dstLayout.layout,
3424                                     size.size, size.layerCount, imageToImage.imageToImageCopy, imageToImage.memcpy,
3425                                     tiling.tiling, offset.offset));
3426                             }
3427                             sizeGroup->addChild(offsetGroup);
3428                         }
3429                         dstLayoutGroup->addChild(sizeGroup);
3430                     }
3431                     srcLayoutGroup->addChild(dstLayoutGroup);
3432                 }
3433                 imageToImageCopyGroup->addChild(srcLayoutGroup);
3434             }
3435             tilingGroup->addChild(imageToImageCopyGroup);
3436         }
3437         group->addChild(tilingGroup);
3438     }
3439 
3440     tcu::TestCaseGroup *const propertiesGroup = new tcu::TestCaseGroup(testCtx, "properties");
3441     propertiesGroup->addChild(new PropertiesTestCase(testCtx, "properties"));
3442 
3443     const struct QueryFormats
3444     {
3445         vk::VkFormat format;
3446     } queryFormats[] = {
3447         {vk::VK_FORMAT_R8G8B8A8_UNORM},    {vk::VK_FORMAT_R32G32B32A32_SFLOAT}, {vk::VK_FORMAT_R16_UNORM},
3448         {vk::VK_FORMAT_R16G16_UINT},       {vk::VK_FORMAT_B8G8R8A8_SINT},       {vk::VK_FORMAT_R16_SFLOAT},
3449         {vk::VK_FORMAT_D24_UNORM_S8_UINT}, {vk::VK_FORMAT_D32_SFLOAT},          {vk::VK_FORMAT_BC7_UNORM_BLOCK},
3450         {vk::VK_FORMAT_BC5_SNORM_BLOCK},
3451     };
3452 
3453     group->addChild(propertiesGroup);
3454 
3455     tcu::TestCaseGroup *const queryGroup = new tcu::TestCaseGroup(testCtx, "query");
3456 
3457     for (const auto &tiling : tilingTests)
3458     {
3459         tcu::TestCaseGroup *const tilingGroup = new tcu::TestCaseGroup(testCtx, tiling.name);
3460         for (const auto &format : queryFormats)
3461         {
3462             const auto formatName = getFormatShortString(format.format);
3463             tilingGroup->addChild(new QueryTestCase(testCtx, formatName.c_str(), format.format, tiling.tiling));
3464         }
3465         queryGroup->addChild(tilingGroup);
3466     }
3467 
3468     group->addChild(queryGroup);
3469 
3470     tcu::TestCaseGroup *const identicalMemoryLayoutGroup = new tcu::TestCaseGroup(testCtx, "identical_memory_layout");
3471 
3472     for (const auto &tiling : tilingTests)
3473     {
3474         tcu::TestCaseGroup *const tilingGroup = new tcu::TestCaseGroup(testCtx, tiling.name);
3475         for (const auto &format : queryFormats)
3476         {
3477             const auto formatName = getFormatShortString(format.format);
3478             tilingGroup->addChild(
3479                 new IdenticalMemoryLayoutTestCase(testCtx, formatName.c_str(), format.format, tiling.tiling));
3480         }
3481         identicalMemoryLayoutGroup->addChild(tilingGroup);
3482     }
3483 
3484     {
3485         const std::vector<VkFormat> dsFormats{
3486             VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,         VK_FORMAT_S8_UINT,
3487             VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_D32_SFLOAT_S8_UINT,
3488         };
3489 
3490         de::MovePtr<tcu::TestCaseGroup> depthStencilGroup(new tcu::TestCaseGroup(testCtx, "depth_stencil"));
3491         for (const auto &format : dsFormats)
3492         {
3493             const DepthStencilHICParams params{
3494                 format,
3495                 tcu::IVec2(256, 256),
3496             };
3497             const auto testName = getFormatShortString(format);
3498             depthStencilGroup->addChild(new DepthStencilHostImageCopyTest(testCtx, testName, params));
3499         }
3500 
3501         group->addChild(depthStencilGroup.release());
3502     }
3503 
3504     group->addChild(identicalMemoryLayoutGroup);
3505 }
3506 
3507 } // namespace
3508 
createImageHostImageCopyTests(tcu::TestContext & testCtx)3509 tcu::TestCaseGroup *createImageHostImageCopyTests(tcu::TestContext &testCtx)
3510 {
3511     de::MovePtr<tcu::TestCaseGroup> testGroup(createTestGroup(testCtx, "host_image_copy", testGenerator));
3512     return testGroup.release();
3513 }
3514 
3515 } // namespace image
3516 } // namespace vkt
3517