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 ¶meters)
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, ©MemoryToImageInfo);
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 ©Region);
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 ®ion, // const VkImageToMemoryCopyEXT* pRegions;
865 };
866 vk.copyImageToMemoryEXT(device, ©ImageToMemoryInfo);
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, ©MemoryToImageInfo);
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, ©Region);
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, ©ImageToMemoryInfo);
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 ¶meters)
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 ®ion, // const VkImageCopy2* pRegions;
1537 };
1538
1539 vk.copyImageToImageEXT(device, ©ImageToImageInfo);
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 ®ion, // const VkImageToMemoryCopyEXT* pRegions;
1567 };
1568 vk.copyImageToMemoryEXT(device, ©ImageToMemoryInfo);
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 ©Region);
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, ©Region);
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, ©Region);
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, ©Region);
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, ©Region);
2343 vk.cmdCopyBuffer(*cmdBuffer, *hostXferBuffer, *hostXferVerifBuffer, 1u, ©Region);
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 ¶ms)
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 ¶ms)
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 ©Region, // const VkMemoryToImageCopyEXT* pRegions;
2610 };
2611
2612 vkd.copyMemoryToImageEXT(device, ©Info);
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 ©Region, // const VkImageToMemoryCopyEXT* pRegions;
2638 };
2639
2640 vkd.copyImageToMemoryEXT(device, ©Info);
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 © : 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