1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2022 Google Inc.
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief YCbCr image offset tests
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "vktYCbCrImageOffsetTests.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp"
27e5c31af7Sopenharmony_ci#include "vktTestGroupUtil.hpp"
28e5c31af7Sopenharmony_ci#include "vktYCbCrUtil.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
31e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
32e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
33e5c31af7Sopenharmony_ci
34e5c31af7Sopenharmony_ci#include <string>
35e5c31af7Sopenharmony_ci#include <vector>
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ciusing tcu::UVec2;
38e5c31af7Sopenharmony_ciusing tcu::TestLog;
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_ciusing std::string;
41e5c31af7Sopenharmony_ciusing std::vector;
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_ciusing namespace vk;
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_cinamespace vkt
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_cinamespace ycbcr
48e5c31af7Sopenharmony_ci{
49e5c31af7Sopenharmony_cinamespace
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_ci	struct TestConfig
53e5c31af7Sopenharmony_ci	{
54e5c31af7Sopenharmony_ci		TestConfig (const vk::VkFormat format_) : format (format_) {}
55e5c31af7Sopenharmony_ci		vk::VkFormat format;
56e5c31af7Sopenharmony_ci	};
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci	void checkSupport (Context& context, const TestConfig config)
59e5c31af7Sopenharmony_ci	{
60e5c31af7Sopenharmony_ci		const vk::VkFormatProperties properties = vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
61e5c31af7Sopenharmony_ci																						context.getPhysicalDevice(), config.format);
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci		if ((properties.linearTilingFeatures & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0)
64e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format doesn't support disjoint planes");
65e5c31af7Sopenharmony_ci	}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	vk::Move<vk::VkImage> createImage (const vk::DeviceInterface&	vkd,
68e5c31af7Sopenharmony_ci									   vk::VkDevice					device,
69e5c31af7Sopenharmony_ci									   vk::VkFormat					format,
70e5c31af7Sopenharmony_ci									   const UVec2&					size)
71e5c31af7Sopenharmony_ci	{
72e5c31af7Sopenharmony_ci		const vk::VkImageCreateInfo createInfo =
73e5c31af7Sopenharmony_ci		{
74e5c31af7Sopenharmony_ci			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
75e5c31af7Sopenharmony_ci			DE_NULL,
76e5c31af7Sopenharmony_ci			vk::VK_IMAGE_CREATE_DISJOINT_BIT,
77e5c31af7Sopenharmony_ci			vk::VK_IMAGE_TYPE_2D,
78e5c31af7Sopenharmony_ci			format,
79e5c31af7Sopenharmony_ci			vk::makeExtent3D(size.x(), size.y(), 1u),
80e5c31af7Sopenharmony_ci			1u,
81e5c31af7Sopenharmony_ci			1u,
82e5c31af7Sopenharmony_ci			vk::VK_SAMPLE_COUNT_1_BIT,
83e5c31af7Sopenharmony_ci			vk::VK_IMAGE_TILING_LINEAR,
84e5c31af7Sopenharmony_ci			vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
85e5c31af7Sopenharmony_ci			vk::VK_SHARING_MODE_EXCLUSIVE,
86e5c31af7Sopenharmony_ci			0u,
87e5c31af7Sopenharmony_ci			(const deUint32*)DE_NULL,
88e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_PREINITIALIZED
89e5c31af7Sopenharmony_ci		};
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci		return vk::createImage(vkd, device, &createInfo);
92e5c31af7Sopenharmony_ci	}
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci	tcu::TestStatus imageOffsetTest (Context& context, const TestConfig config)
95e5c31af7Sopenharmony_ci	{
96e5c31af7Sopenharmony_ci		const vk::DeviceInterface&				vkd						(context.getDeviceInterface());
97e5c31af7Sopenharmony_ci		const vk::VkDevice						device					(context.getDevice());
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci		const vk::Unique<vk::VkImage>			srcImage				(createImage(vkd, device, config.format, UVec2(8u, 8u)));
100e5c31af7Sopenharmony_ci		const vk::MemoryRequirement				srcMemoryRequirement	(vk::MemoryRequirement::HostVisible);
101e5c31af7Sopenharmony_ci		vector<AllocationSp>					srcImageMemory;
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_ci		const deUint32							numPlanes				= getPlaneCount(config.format);
104e5c31af7Sopenharmony_ci		vector<vk::VkBindImageMemoryInfo>		coreInfos;
105e5c31af7Sopenharmony_ci		vector<vk::VkBindImagePlaneMemoryInfo>	planeInfos;
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci		coreInfos.reserve(numPlanes);
108e5c31af7Sopenharmony_ci		planeInfos.reserve(numPlanes);
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci		for (deUint32 planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
111e5c31af7Sopenharmony_ci		{
112e5c31af7Sopenharmony_ci			const vk::VkImageAspectFlagBits	planeAspect	= (vk::VkImageAspectFlagBits)(vk::VK_IMAGE_ASPECT_PLANE_0_BIT << planeNdx);
113e5c31af7Sopenharmony_ci			vk::VkMemoryRequirements		reqs		= getImagePlaneMemoryRequirements(vkd, device, srcImage.get(), planeAspect);
114e5c31af7Sopenharmony_ci			const VkDeviceSize				offset		= deAlign64(reqs.size, reqs.alignment);
115e5c31af7Sopenharmony_ci			reqs.size *= 2;
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci			srcImageMemory.push_back(AllocationSp(context.getDefaultAllocator().allocate(reqs, srcMemoryRequirement).release()));
118e5c31af7Sopenharmony_ci
119e5c31af7Sopenharmony_ci			vk::VkBindImagePlaneMemoryInfo	planeInfo	=
120e5c31af7Sopenharmony_ci			{
121e5c31af7Sopenharmony_ci				vk::VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO,
122e5c31af7Sopenharmony_ci				DE_NULL,
123e5c31af7Sopenharmony_ci				planeAspect
124e5c31af7Sopenharmony_ci			};
125e5c31af7Sopenharmony_ci			planeInfos.push_back(planeInfo);
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci			vk::VkBindImageMemoryInfo		coreInfo	=
128e5c31af7Sopenharmony_ci			{
129e5c31af7Sopenharmony_ci				vk::VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
130e5c31af7Sopenharmony_ci				&planeInfos.back(),
131e5c31af7Sopenharmony_ci				srcImage.get(),
132e5c31af7Sopenharmony_ci				srcImageMemory.back()->getMemory(),
133e5c31af7Sopenharmony_ci				offset,
134e5c31af7Sopenharmony_ci			};
135e5c31af7Sopenharmony_ci			coreInfos.push_back(coreInfo);
136e5c31af7Sopenharmony_ci		}
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ci		VK_CHECK(vkd.bindImageMemory2(device, numPlanes, coreInfos.data()));
139e5c31af7Sopenharmony_ci
140e5c31af7Sopenharmony_ci		vk::VkImageAspectFlags					aspectMasks[3] = {vk::VK_IMAGE_ASPECT_PLANE_0_BIT, vk::VK_IMAGE_ASPECT_PLANE_1_BIT,
141e5c31af7Sopenharmony_ci																  vk::VK_IMAGE_ASPECT_PLANE_2_BIT};
142e5c31af7Sopenharmony_ci		for (deUint32 i = 0; i < numPlanes; i++)
143e5c31af7Sopenharmony_ci		{
144e5c31af7Sopenharmony_ci			vk::VkSubresourceLayout	subresourceLayout;
145e5c31af7Sopenharmony_ci			auto					subresource		= vk::makeImageSubresource(aspectMasks[i], 0u, 0u);
146e5c31af7Sopenharmony_ci			vkd.getImageSubresourceLayout(device, srcImage.get(), &subresource, &subresourceLayout);
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci			// VkSubresourceLayout::offset is the byte offset from the start of the image or the plane
149e5c31af7Sopenharmony_ci			// where the image subresource begins. For disjoint images, it should be 0 since each plane
150e5c31af7Sopenharmony_ci			// has been separately bound to memory.
151e5c31af7Sopenharmony_ci			if (subresourceLayout.offset != 0)
152e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("Failed, subresource layout offset != 0");
153e5c31af7Sopenharmony_ci		}
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Pass");
156e5c31af7Sopenharmony_ci	}
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_ci	void initYcbcrImageOffsetTests (tcu::TestCaseGroup* testGroup)
159e5c31af7Sopenharmony_ci	{
160e5c31af7Sopenharmony_ci		const vk::VkFormat ycbcrFormats[] =
161e5c31af7Sopenharmony_ci		{
162e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
163e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
164e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
165e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
166e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
167e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
168e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
169e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
170e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
171e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
172e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
173e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
174e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
175e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
176e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
177e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
178e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
179e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
180e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
181e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
182e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
183e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM,
184e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16,
185e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16,
186e5c31af7Sopenharmony_ci			vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM,
187e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
188e5c31af7Sopenharmony_ci		};
189e5c31af7Sopenharmony_ci
190e5c31af7Sopenharmony_ci		for (int i = 0; i < DE_LENGTH_OF_ARRAY(ycbcrFormats); i++)
191e5c31af7Sopenharmony_ci		{
192e5c31af7Sopenharmony_ci			const vk::VkFormat	srcFormat		(ycbcrFormats[i]);
193e5c31af7Sopenharmony_ci			const string		srcFormatName	(de::toLower(std::string(getFormatName(srcFormat)).substr(10)));
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ci			const TestConfig	config			(srcFormat);
196e5c31af7Sopenharmony_ci			addFunctionCase(testGroup, srcFormatName.c_str(), checkSupport, imageOffsetTest, config);
197e5c31af7Sopenharmony_ci		}
198e5c31af7Sopenharmony_ci	}
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci} // anonymous
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageOffsetTests  (tcu::TestContext& testCtx)
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	return createTestGroup(testCtx, "subresource_offset", initYcbcrImageOffsetTests);
205e5c31af7Sopenharmony_ci}
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci} // ycbcr
208e5c31af7Sopenharmony_ci} // vkt
209