1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2019 Google Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2019 The Khronos Group Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci *//*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief YCbCr Test Utilities
23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "vktYCbCrUtil.hpp"
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
28e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
29e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
30e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
33e5c31af7Sopenharmony_ci#include "deMath.h"
34e5c31af7Sopenharmony_ci#include "deFloat16.h"
35e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
36e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ci#include "deSTLUtil.hpp"
39e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include <limits>
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_cinamespace vkt
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_cinamespace ycbcr
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ciusing namespace vk;
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ciusing de::MovePtr;
51e5c31af7Sopenharmony_ciusing tcu::FloatFormat;
52e5c31af7Sopenharmony_ciusing tcu::Interval;
53e5c31af7Sopenharmony_ciusing tcu::IVec2;
54e5c31af7Sopenharmony_ciusing tcu::IVec4;
55e5c31af7Sopenharmony_ciusing tcu::UVec2;
56e5c31af7Sopenharmony_ciusing tcu::UVec4;
57e5c31af7Sopenharmony_ciusing tcu::Vec2;
58e5c31af7Sopenharmony_ciusing tcu::Vec4;
59e5c31af7Sopenharmony_ciusing std::vector;
60e5c31af7Sopenharmony_ciusing std::string;
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ci// MultiPlaneImageData
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_ciMultiPlaneImageData::MultiPlaneImageData (VkFormat format, const UVec2& size)
65e5c31af7Sopenharmony_ci	: m_format		(format)
66e5c31af7Sopenharmony_ci	, m_description	(getPlanarFormatDescription(format))
67e5c31af7Sopenharmony_ci	, m_size		(size)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < m_description.numPlanes; ++planeNdx)
70e5c31af7Sopenharmony_ci		m_planeData[planeNdx].resize(getPlaneSizeInBytes(m_description, size, planeNdx, 0, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY));
71e5c31af7Sopenharmony_ci}
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ciMultiPlaneImageData::MultiPlaneImageData (const MultiPlaneImageData& other)
74e5c31af7Sopenharmony_ci	: m_format		(other.m_format)
75e5c31af7Sopenharmony_ci	, m_description	(other.m_description)
76e5c31af7Sopenharmony_ci	, m_size		(other.m_size)
77e5c31af7Sopenharmony_ci{
78e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < m_description.numPlanes; ++planeNdx)
79e5c31af7Sopenharmony_ci		m_planeData[planeNdx] = other.m_planeData[planeNdx];
80e5c31af7Sopenharmony_ci}
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ciMultiPlaneImageData::~MultiPlaneImageData (void)
83e5c31af7Sopenharmony_ci{
84e5c31af7Sopenharmony_ci}
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_citcu::PixelBufferAccess MultiPlaneImageData::getChannelAccess (deUint32 channelNdx)
87e5c31af7Sopenharmony_ci{
88e5c31af7Sopenharmony_ci	void*		planePtrs[PlanarFormatDescription::MAX_PLANES];
89e5c31af7Sopenharmony_ci	deUint32	planeRowPitches[PlanarFormatDescription::MAX_PLANES];
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < m_description.numPlanes; ++planeNdx)
92e5c31af7Sopenharmony_ci	{
93e5c31af7Sopenharmony_ci		const deUint32	planeW		= m_size.x() / ( m_description.blockWidth * m_description.planes[planeNdx].widthDivisor);
94e5c31af7Sopenharmony_ci		planeRowPitches[planeNdx]	= m_description.planes[planeNdx].elementSizeBytes * planeW;
95e5c31af7Sopenharmony_ci		planePtrs[planeNdx]			= &m_planeData[planeNdx][0];
96e5c31af7Sopenharmony_ci	}
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci	return vk::getChannelAccess(m_description,
99e5c31af7Sopenharmony_ci								m_size,
100e5c31af7Sopenharmony_ci								planeRowPitches,
101e5c31af7Sopenharmony_ci								planePtrs,
102e5c31af7Sopenharmony_ci								channelNdx);
103e5c31af7Sopenharmony_ci}
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_citcu::ConstPixelBufferAccess MultiPlaneImageData::getChannelAccess (deUint32 channelNdx) const
106e5c31af7Sopenharmony_ci{
107e5c31af7Sopenharmony_ci	const void*	planePtrs[PlanarFormatDescription::MAX_PLANES];
108e5c31af7Sopenharmony_ci	deUint32	planeRowPitches[PlanarFormatDescription::MAX_PLANES];
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < m_description.numPlanes; ++planeNdx)
111e5c31af7Sopenharmony_ci	{
112e5c31af7Sopenharmony_ci		const deUint32	planeW		= m_size.x() / (m_description.blockWidth * m_description.planes[planeNdx].widthDivisor);
113e5c31af7Sopenharmony_ci		planeRowPitches[planeNdx]	= m_description.planes[planeNdx].elementSizeBytes * planeW;
114e5c31af7Sopenharmony_ci		planePtrs[planeNdx]			= &m_planeData[planeNdx][0];
115e5c31af7Sopenharmony_ci	}
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci	return vk::getChannelAccess(m_description,
118e5c31af7Sopenharmony_ci								m_size,
119e5c31af7Sopenharmony_ci								planeRowPitches,
120e5c31af7Sopenharmony_ci								planePtrs,
121e5c31af7Sopenharmony_ci								channelNdx);
122e5c31af7Sopenharmony_ci}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci// Misc utilities
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_cinamespace
127e5c31af7Sopenharmony_ci{
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_civoid allocateStagingBuffers (const DeviceInterface&			vkd,
130e5c31af7Sopenharmony_ci							 VkDevice						device,
131e5c31af7Sopenharmony_ci							 Allocator&						allocator,
132e5c31af7Sopenharmony_ci							 const MultiPlaneImageData&		imageData,
133e5c31af7Sopenharmony_ci							 vector<VkBufferSp>*			buffers,
134e5c31af7Sopenharmony_ci							 vector<AllocationSp>*			allocations)
135e5c31af7Sopenharmony_ci{
136e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
137e5c31af7Sopenharmony_ci	{
138e5c31af7Sopenharmony_ci		const VkBufferCreateInfo	bufferInfo	=
139e5c31af7Sopenharmony_ci		{
140e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
141e5c31af7Sopenharmony_ci			DE_NULL,
142e5c31af7Sopenharmony_ci			(VkBufferCreateFlags)0u,
143e5c31af7Sopenharmony_ci			(VkDeviceSize)imageData.getPlaneSize(planeNdx),
144e5c31af7Sopenharmony_ci			VK_BUFFER_USAGE_TRANSFER_SRC_BIT|VK_BUFFER_USAGE_TRANSFER_DST_BIT,
145e5c31af7Sopenharmony_ci			VK_SHARING_MODE_EXCLUSIVE,
146e5c31af7Sopenharmony_ci			0u,
147e5c31af7Sopenharmony_ci			(const deUint32*)DE_NULL,
148e5c31af7Sopenharmony_ci		};
149e5c31af7Sopenharmony_ci		Move<VkBuffer>				buffer		(createBuffer(vkd, device, &bufferInfo));
150e5c31af7Sopenharmony_ci		MovePtr<Allocation>			allocation	(allocator.allocate(getBufferMemoryRequirements(vkd, device, *buffer),
151e5c31af7Sopenharmony_ci																	MemoryRequirement::HostVisible|MemoryRequirement::Any));
152e5c31af7Sopenharmony_ci
153e5c31af7Sopenharmony_ci		VK_CHECK(vkd.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci		buffers->push_back(VkBufferSp(new Unique<VkBuffer>(buffer)));
156e5c31af7Sopenharmony_ci		allocations->push_back(AllocationSp(allocation.release()));
157e5c31af7Sopenharmony_ci	}
158e5c31af7Sopenharmony_ci}
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_civoid allocateAndWriteStagingBuffers (const DeviceInterface&		vkd,
161e5c31af7Sopenharmony_ci									  VkDevice						device,
162e5c31af7Sopenharmony_ci									  Allocator&					allocator,
163e5c31af7Sopenharmony_ci									  const MultiPlaneImageData&	imageData,
164e5c31af7Sopenharmony_ci									  vector<VkBufferSp>*			buffers,
165e5c31af7Sopenharmony_ci									  vector<AllocationSp>*			allocations)
166e5c31af7Sopenharmony_ci{
167e5c31af7Sopenharmony_ci	allocateStagingBuffers(vkd, device, allocator, imageData, buffers, allocations);
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
170e5c31af7Sopenharmony_ci	{
171e5c31af7Sopenharmony_ci		deMemcpy((*allocations)[planeNdx]->getHostPtr(), imageData.getPlanePtr(planeNdx), imageData.getPlaneSize(planeNdx));
172e5c31af7Sopenharmony_ci		flushMappedMemoryRange(vkd, device, (*allocations)[planeNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
173e5c31af7Sopenharmony_ci	}
174e5c31af7Sopenharmony_ci}
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_civoid readStagingBuffers (MultiPlaneImageData*			imageData,
177e5c31af7Sopenharmony_ci						 const DeviceInterface&			vkd,
178e5c31af7Sopenharmony_ci						 VkDevice						device,
179e5c31af7Sopenharmony_ci						 const vector<AllocationSp>&	allocations)
180e5c31af7Sopenharmony_ci{
181e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData->getDescription().numPlanes; ++planeNdx)
182e5c31af7Sopenharmony_ci	{
183e5c31af7Sopenharmony_ci		invalidateMappedMemoryRange(vkd, device, allocations[planeNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
184e5c31af7Sopenharmony_ci		deMemcpy(imageData->getPlanePtr(planeNdx), allocations[planeNdx]->getHostPtr(), imageData->getPlaneSize(planeNdx));
185e5c31af7Sopenharmony_ci	}
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci} // anonymous
189e5c31af7Sopenharmony_ci
190e5c31af7Sopenharmony_civoid checkImageSupport (Context& context, VkFormat format, VkImageCreateFlags createFlags, VkImageTiling tiling)
191e5c31af7Sopenharmony_ci{
192e5c31af7Sopenharmony_ci	const bool													disjoint	= (createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0;
193e5c31af7Sopenharmony_ci	const VkPhysicalDeviceSamplerYcbcrConversionFeatures		features	= context.getSamplerYcbcrConversionFeatures();
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ci	if (features.samplerYcbcrConversion == VK_FALSE)
196e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "samplerYcbcrConversion is not supported");
197e5c31af7Sopenharmony_ci
198e5c31af7Sopenharmony_ci	if (disjoint)
199e5c31af7Sopenharmony_ci	{
200e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_bind_memory2");
201e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_get_memory_requirements2");
202e5c31af7Sopenharmony_ci	}
203e5c31af7Sopenharmony_ci
204e5c31af7Sopenharmony_ci	{
205e5c31af7Sopenharmony_ci		const VkFormatProperties	formatProperties	= getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
206e5c31af7Sopenharmony_ci																							context.getPhysicalDevice(),
207e5c31af7Sopenharmony_ci																							format);
208e5c31af7Sopenharmony_ci		const VkFormatFeatureFlags	featureFlags		= tiling == VK_IMAGE_TILING_OPTIMAL
209e5c31af7Sopenharmony_ci														? formatProperties.optimalTilingFeatures
210e5c31af7Sopenharmony_ci														: formatProperties.linearTilingFeatures;
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci		if ((featureFlags & (VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) == 0)
213e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "YCbCr conversion is not supported for format");
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci		if (disjoint && ((featureFlags & VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
216e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Disjoint planes are not supported for format");
217e5c31af7Sopenharmony_ci	}
218e5c31af7Sopenharmony_ci}
219e5c31af7Sopenharmony_ci
220e5c31af7Sopenharmony_civoid fillRandomNoNaN(de::Random* randomGen, deUint8* const data, deUint32 size, const vk::VkFormat format)
221e5c31af7Sopenharmony_ci{
222e5c31af7Sopenharmony_ci	bool isFloat = false;
223e5c31af7Sopenharmony_ci	deUint32 stride = 1;
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_ci	switch (format)
226e5c31af7Sopenharmony_ci	{
227e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_B10G11R11_UFLOAT_PACK32:
228e5c31af7Sopenharmony_ci		isFloat = true;
229e5c31af7Sopenharmony_ci		stride = 1;
230e5c31af7Sopenharmony_ci		break;
231e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R16_SFLOAT:
232e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R16G16_SFLOAT:
233e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R16G16B16_SFLOAT:
234e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R16G16B16A16_SFLOAT:
235e5c31af7Sopenharmony_ci		isFloat = true;
236e5c31af7Sopenharmony_ci		stride = 2;
237e5c31af7Sopenharmony_ci		break;
238e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R32_SFLOAT:
239e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R32G32_SFLOAT:
240e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R32G32B32_SFLOAT:
241e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R32G32B32A32_SFLOAT:
242e5c31af7Sopenharmony_ci		isFloat = true;
243e5c31af7Sopenharmony_ci		stride = 4;
244e5c31af7Sopenharmony_ci		break;
245e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R64_SFLOAT:
246e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R64G64_SFLOAT:
247e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R64G64B64_SFLOAT:
248e5c31af7Sopenharmony_ci	case vk::VK_FORMAT_R64G64B64A64_SFLOAT:
249e5c31af7Sopenharmony_ci		isFloat = true;
250e5c31af7Sopenharmony_ci		stride = 8;
251e5c31af7Sopenharmony_ci		break;
252e5c31af7Sopenharmony_ci	default:
253e5c31af7Sopenharmony_ci		stride = 1;
254e5c31af7Sopenharmony_ci		break;
255e5c31af7Sopenharmony_ci	}
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci	if (isFloat) {
258e5c31af7Sopenharmony_ci		deUint32 ndx = 0;
259e5c31af7Sopenharmony_ci		for (; ndx < size - stride + 1; ndx += stride)
260e5c31af7Sopenharmony_ci		{
261e5c31af7Sopenharmony_ci			if (stride == 1) {
262e5c31af7Sopenharmony_ci				// Set first bit of each channel to 0 to avoid NaNs, only format is B10G11R11
263e5c31af7Sopenharmony_ci				const deUint8 mask[] = { 0x7F, 0xDF, 0xFB, 0xFF };
264e5c31af7Sopenharmony_ci				// Apply mask for both endians
265e5c31af7Sopenharmony_ci				data[ndx] = (randomGen->getUint8() & mask[ndx % 4]) & mask[3 - ndx % 4];
266e5c31af7Sopenharmony_ci			}
267e5c31af7Sopenharmony_ci			else if (stride == 2)
268e5c31af7Sopenharmony_ci			{
269e5c31af7Sopenharmony_ci				deFloat16* ptr = reinterpret_cast<deFloat16*>(&data[ndx]);
270e5c31af7Sopenharmony_ci				*ptr = deFloat32To16(randomGen->getFloat());
271e5c31af7Sopenharmony_ci			}
272e5c31af7Sopenharmony_ci			else if (stride == 4)
273e5c31af7Sopenharmony_ci			{
274e5c31af7Sopenharmony_ci				float* ptr = reinterpret_cast<float*>(&data[ndx]);
275e5c31af7Sopenharmony_ci				*ptr = randomGen->getFloat();
276e5c31af7Sopenharmony_ci			}
277e5c31af7Sopenharmony_ci			else if (stride == 8)
278e5c31af7Sopenharmony_ci			{
279e5c31af7Sopenharmony_ci				double* ptr = reinterpret_cast<double*>(&data[ndx]);
280e5c31af7Sopenharmony_ci				*ptr = randomGen->getDouble();
281e5c31af7Sopenharmony_ci			}
282e5c31af7Sopenharmony_ci		}
283e5c31af7Sopenharmony_ci		while (ndx < size) {
284e5c31af7Sopenharmony_ci			data[ndx] = 0;
285e5c31af7Sopenharmony_ci		}
286e5c31af7Sopenharmony_ci	}
287e5c31af7Sopenharmony_ci	else
288e5c31af7Sopenharmony_ci	{
289e5c31af7Sopenharmony_ci		for (deUint32 ndx = 0; ndx < size; ++ndx)
290e5c31af7Sopenharmony_ci		{
291e5c31af7Sopenharmony_ci			data[ndx] = randomGen->getUint8();
292e5c31af7Sopenharmony_ci		}
293e5c31af7Sopenharmony_ci	}
294e5c31af7Sopenharmony_ci}
295e5c31af7Sopenharmony_ci
296e5c31af7Sopenharmony_ci// When noNan is true, fillRandom does not generate NaNs in float formats.
297e5c31af7Sopenharmony_civoid fillRandom (de::Random* randomGen, MultiPlaneImageData* imageData, const vk::VkFormat format, const bool noNan)
298e5c31af7Sopenharmony_ci{
299e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData->getDescription().numPlanes; ++planeNdx)
300e5c31af7Sopenharmony_ci	{
301e5c31af7Sopenharmony_ci		const size_t	planeSize	= imageData->getPlaneSize(planeNdx);
302e5c31af7Sopenharmony_ci		deUint8* const	planePtr	= (deUint8*)imageData->getPlanePtr(planeNdx);
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci		if (noNan) {
305e5c31af7Sopenharmony_ci			fillRandomNoNaN(randomGen, planePtr, (deUint32)planeSize, format);
306e5c31af7Sopenharmony_ci		}
307e5c31af7Sopenharmony_ci		else
308e5c31af7Sopenharmony_ci		{
309e5c31af7Sopenharmony_ci			for (size_t ndx = 0; ndx < planeSize; ++ndx)
310e5c31af7Sopenharmony_ci			{
311e5c31af7Sopenharmony_ci				planePtr[ndx] = randomGen->getUint8();
312e5c31af7Sopenharmony_ci			}
313e5c31af7Sopenharmony_ci		}
314e5c31af7Sopenharmony_ci	}
315e5c31af7Sopenharmony_ci}
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_civoid fillGradient (MultiPlaneImageData* imageData, const tcu::Vec4& minVal, const tcu::Vec4& maxVal)
318e5c31af7Sopenharmony_ci{
319e5c31af7Sopenharmony_ci	const PlanarFormatDescription&	formatInfo	= imageData->getDescription();
320e5c31af7Sopenharmony_ci
321e5c31af7Sopenharmony_ci	// \todo [pyry] Optimize: no point in re-rendering source gradient for each channel.
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_ci	for (deUint32 channelNdx = 0; channelNdx < 4; channelNdx++)
324e5c31af7Sopenharmony_ci	{
325e5c31af7Sopenharmony_ci		if (formatInfo.hasChannelNdx(channelNdx))
326e5c31af7Sopenharmony_ci		{
327e5c31af7Sopenharmony_ci			const tcu::PixelBufferAccess		channelAccess	= imageData->getChannelAccess(channelNdx);
328e5c31af7Sopenharmony_ci			tcu::TextureLevel					tmpTexture		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),  channelAccess.getWidth(), channelAccess.getHeight());
329e5c31af7Sopenharmony_ci			const tcu::ConstPixelBufferAccess	tmpAccess		= tmpTexture.getAccess();
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_ci			tcu::fillWithComponentGradients(tmpTexture, minVal, maxVal);
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_ci			for (int y = 0; y < channelAccess.getHeight(); ++y)
334e5c31af7Sopenharmony_ci			for (int x = 0; x < channelAccess.getWidth(); ++x)
335e5c31af7Sopenharmony_ci			{
336e5c31af7Sopenharmony_ci				channelAccess.setPixel(tcu::Vec4(tmpAccess.getPixel(x, y)[channelNdx]), x, y);
337e5c31af7Sopenharmony_ci			}
338e5c31af7Sopenharmony_ci		}
339e5c31af7Sopenharmony_ci	}
340e5c31af7Sopenharmony_ci}
341e5c31af7Sopenharmony_ci
342e5c31af7Sopenharmony_civoid fillZero (MultiPlaneImageData* imageData)
343e5c31af7Sopenharmony_ci{
344e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData->getDescription().numPlanes; ++planeNdx)
345e5c31af7Sopenharmony_ci		deMemset(imageData->getPlanePtr(planeNdx), 0, imageData->getPlaneSize(planeNdx));
346e5c31af7Sopenharmony_ci}
347e5c31af7Sopenharmony_ci
348e5c31af7Sopenharmony_civector<AllocationSp> allocateAndBindImageMemory (const DeviceInterface&	vkd,
349e5c31af7Sopenharmony_ci												 VkDevice				device,
350e5c31af7Sopenharmony_ci												 Allocator&				allocator,
351e5c31af7Sopenharmony_ci												 VkImage				image,
352e5c31af7Sopenharmony_ci												 VkFormat				format,
353e5c31af7Sopenharmony_ci												 VkImageCreateFlags		createFlags,
354e5c31af7Sopenharmony_ci												 vk::MemoryRequirement	requirement)
355e5c31af7Sopenharmony_ci{
356e5c31af7Sopenharmony_ci	vector<AllocationSp> allocations;
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci	if ((createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0)
359e5c31af7Sopenharmony_ci	{
360e5c31af7Sopenharmony_ci		const deUint32	numPlanes	= getPlaneCount(format);
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci		bindImagePlanesMemory(vkd, device, image, numPlanes, allocations, allocator, requirement);
363e5c31af7Sopenharmony_ci	}
364e5c31af7Sopenharmony_ci	else
365e5c31af7Sopenharmony_ci	{
366e5c31af7Sopenharmony_ci		const VkMemoryRequirements	reqs	= getImageMemoryRequirements(vkd, device, image);
367e5c31af7Sopenharmony_ci
368e5c31af7Sopenharmony_ci		allocations.push_back(AllocationSp(allocator.allocate(reqs, requirement).release()));
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci		VK_CHECK(vkd.bindImageMemory(device, image, allocations.back()->getMemory(), allocations.back()->getOffset()));
371e5c31af7Sopenharmony_ci	}
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_ci	return allocations;
374e5c31af7Sopenharmony_ci}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_civoid uploadImage (const DeviceInterface&		vkd,
377e5c31af7Sopenharmony_ci				  VkDevice						device,
378e5c31af7Sopenharmony_ci				  deUint32						queueFamilyNdx,
379e5c31af7Sopenharmony_ci				  Allocator&					allocator,
380e5c31af7Sopenharmony_ci				  VkImage						image,
381e5c31af7Sopenharmony_ci				  const MultiPlaneImageData&	imageData,
382e5c31af7Sopenharmony_ci				  VkAccessFlags					nextAccess,
383e5c31af7Sopenharmony_ci				  VkImageLayout					finalLayout,
384e5c31af7Sopenharmony_ci				  deUint32						arrayLayer)
385e5c31af7Sopenharmony_ci{
386e5c31af7Sopenharmony_ci	const VkQueue					queue			= getDeviceQueue(vkd, device, queueFamilyNdx, 0u);
387e5c31af7Sopenharmony_ci	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx));
388e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
389e5c31af7Sopenharmony_ci	vector<VkBufferSp>				stagingBuffers;
390e5c31af7Sopenharmony_ci	vector<AllocationSp>			stagingMemory;
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_ci	const PlanarFormatDescription&	formatDesc		= imageData.getDescription();
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	allocateAndWriteStagingBuffers(vkd, device, allocator, imageData, &stagingBuffers, &stagingMemory);
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_ci	beginCommandBuffer(vkd, *cmdBuffer);
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
399e5c31af7Sopenharmony_ci	{
400e5c31af7Sopenharmony_ci		const VkImageAspectFlagBits	aspect	= (formatDesc.numPlanes > 1)
401e5c31af7Sopenharmony_ci											? getPlaneAspect(planeNdx)
402e5c31af7Sopenharmony_ci											: VK_IMAGE_ASPECT_COLOR_BIT;
403e5c31af7Sopenharmony_ci		const VkExtent3D imageExtent		= makeExtent3D(imageData.getSize().x(), imageData.getSize().y(), 1u);
404e5c31af7Sopenharmony_ci		const VkExtent3D planeExtent		= getPlaneExtent(formatDesc, imageExtent, planeNdx, 0);
405e5c31af7Sopenharmony_ci		const VkBufferImageCopy		copy	=
406e5c31af7Sopenharmony_ci		{
407e5c31af7Sopenharmony_ci			0u,		// bufferOffset
408e5c31af7Sopenharmony_ci			0u,		// bufferRowLength
409e5c31af7Sopenharmony_ci			0u,		// bufferImageHeight
410e5c31af7Sopenharmony_ci			{ (VkImageAspectFlags)aspect, 0u, arrayLayer, 1u },
411e5c31af7Sopenharmony_ci			makeOffset3D(0u, 0u, 0u),
412e5c31af7Sopenharmony_ci			planeExtent
413e5c31af7Sopenharmony_ci		};
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci		{
416e5c31af7Sopenharmony_ci			const VkImageMemoryBarrier		preCopyBarrier	=
417e5c31af7Sopenharmony_ci				{
418e5c31af7Sopenharmony_ci					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
419e5c31af7Sopenharmony_ci					DE_NULL,
420e5c31af7Sopenharmony_ci					(VkAccessFlags)0,
421e5c31af7Sopenharmony_ci					VK_ACCESS_TRANSFER_WRITE_BIT,
422e5c31af7Sopenharmony_ci					VK_IMAGE_LAYOUT_UNDEFINED,
423e5c31af7Sopenharmony_ci					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
424e5c31af7Sopenharmony_ci					VK_QUEUE_FAMILY_IGNORED,
425e5c31af7Sopenharmony_ci					VK_QUEUE_FAMILY_IGNORED,
426e5c31af7Sopenharmony_ci					image,
427e5c31af7Sopenharmony_ci					{ (VkImageAspectFlags)aspect, 0u, 1u, arrayLayer, 1u }
428e5c31af7Sopenharmony_ci				};
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci			vkd.cmdPipelineBarrier(*cmdBuffer,
431e5c31af7Sopenharmony_ci								   (VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT,
432e5c31af7Sopenharmony_ci								   (VkPipelineStageFlags)VK_PIPELINE_STAGE_TRANSFER_BIT,
433e5c31af7Sopenharmony_ci								   (VkDependencyFlags)0u,
434e5c31af7Sopenharmony_ci								   0u,
435e5c31af7Sopenharmony_ci								   (const VkMemoryBarrier*)DE_NULL,
436e5c31af7Sopenharmony_ci								   0u,
437e5c31af7Sopenharmony_ci								   (const VkBufferMemoryBarrier*)DE_NULL,
438e5c31af7Sopenharmony_ci								   1u,
439e5c31af7Sopenharmony_ci								   &preCopyBarrier);
440e5c31af7Sopenharmony_ci		}
441e5c31af7Sopenharmony_ci
442e5c31af7Sopenharmony_ci		vkd.cmdCopyBufferToImage(*cmdBuffer, **stagingBuffers[planeNdx], image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copy);
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci		{
445e5c31af7Sopenharmony_ci			const VkImageMemoryBarrier		postCopyBarrier	=
446e5c31af7Sopenharmony_ci				{
447e5c31af7Sopenharmony_ci					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
448e5c31af7Sopenharmony_ci					DE_NULL,
449e5c31af7Sopenharmony_ci					VK_ACCESS_TRANSFER_WRITE_BIT,
450e5c31af7Sopenharmony_ci					nextAccess,
451e5c31af7Sopenharmony_ci					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
452e5c31af7Sopenharmony_ci					finalLayout,
453e5c31af7Sopenharmony_ci					VK_QUEUE_FAMILY_IGNORED,
454e5c31af7Sopenharmony_ci					VK_QUEUE_FAMILY_IGNORED,
455e5c31af7Sopenharmony_ci					image,
456e5c31af7Sopenharmony_ci					{ (VkImageAspectFlags)aspect, 0u, 1u, arrayLayer, 1u }
457e5c31af7Sopenharmony_ci				};
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_ci			vkd.cmdPipelineBarrier(*cmdBuffer,
460e5c31af7Sopenharmony_ci								   (VkPipelineStageFlags)VK_PIPELINE_STAGE_TRANSFER_BIT,
461e5c31af7Sopenharmony_ci								   (VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
462e5c31af7Sopenharmony_ci								   (VkDependencyFlags)0u,
463e5c31af7Sopenharmony_ci								   0u,
464e5c31af7Sopenharmony_ci								   (const VkMemoryBarrier*)DE_NULL,
465e5c31af7Sopenharmony_ci								   0u,
466e5c31af7Sopenharmony_ci								   (const VkBufferMemoryBarrier*)DE_NULL,
467e5c31af7Sopenharmony_ci								   1u,
468e5c31af7Sopenharmony_ci								   &postCopyBarrier);
469e5c31af7Sopenharmony_ci		}
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci	}
472e5c31af7Sopenharmony_ci
473e5c31af7Sopenharmony_ci	endCommandBuffer(vkd, *cmdBuffer);
474e5c31af7Sopenharmony_ci
475e5c31af7Sopenharmony_ci	submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
476e5c31af7Sopenharmony_ci}
477e5c31af7Sopenharmony_ci
478e5c31af7Sopenharmony_civoid fillImageMemory (const vk::DeviceInterface&							vkd,
479e5c31af7Sopenharmony_ci					  vk::VkDevice											device,
480e5c31af7Sopenharmony_ci					  deUint32												queueFamilyNdx,
481e5c31af7Sopenharmony_ci					  vk::VkImage											image,
482e5c31af7Sopenharmony_ci					  const std::vector<de::SharedPtr<vk::Allocation> >&	allocations,
483e5c31af7Sopenharmony_ci					  const MultiPlaneImageData&							imageData,
484e5c31af7Sopenharmony_ci					  vk::VkAccessFlags										nextAccess,
485e5c31af7Sopenharmony_ci					  vk::VkImageLayout										finalLayout,
486e5c31af7Sopenharmony_ci					  deUint32												arrayLayer)
487e5c31af7Sopenharmony_ci{
488e5c31af7Sopenharmony_ci	const VkQueue					queue			= getDeviceQueue(vkd, device, queueFamilyNdx, 0u);
489e5c31af7Sopenharmony_ci	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx));
490e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
491e5c31af7Sopenharmony_ci	const PlanarFormatDescription&	formatDesc		= imageData.getDescription();
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < formatDesc.numPlanes; ++planeNdx)
494e5c31af7Sopenharmony_ci	{
495e5c31af7Sopenharmony_ci		const VkImageAspectFlagBits			aspect		= (formatDesc.numPlanes > 1)
496e5c31af7Sopenharmony_ci														? getPlaneAspect(planeNdx)
497e5c31af7Sopenharmony_ci														: VK_IMAGE_ASPECT_COLOR_BIT;
498e5c31af7Sopenharmony_ci		const de::SharedPtr<Allocation>&	allocation	= allocations.size() > 1
499e5c31af7Sopenharmony_ci														? allocations[planeNdx]
500e5c31af7Sopenharmony_ci														: allocations[0];
501e5c31af7Sopenharmony_ci		const size_t						planeSize	= imageData.getPlaneSize(planeNdx);
502e5c31af7Sopenharmony_ci		const deUint32						planeH		= imageData.getSize().y() / formatDesc.planes[planeNdx].heightDivisor;
503e5c31af7Sopenharmony_ci		const VkImageSubresource			subresource	=
504e5c31af7Sopenharmony_ci		{
505e5c31af7Sopenharmony_ci			static_cast<vk::VkImageAspectFlags>(aspect),
506e5c31af7Sopenharmony_ci			0u,
507e5c31af7Sopenharmony_ci			arrayLayer,
508e5c31af7Sopenharmony_ci		};
509e5c31af7Sopenharmony_ci		VkSubresourceLayout			layout;
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci		vkd.getImageSubresourceLayout(device, image, &subresource, &layout);
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci		for (deUint32 row = 0; row < planeH; ++row)
514e5c31af7Sopenharmony_ci		{
515e5c31af7Sopenharmony_ci			const size_t		rowSize		= planeSize / planeH;
516e5c31af7Sopenharmony_ci			void* const			dstPtr		= ((deUint8*)allocation->getHostPtr()) + layout.offset + layout.rowPitch * row;
517e5c31af7Sopenharmony_ci			const void* const	srcPtr		= ((const deUint8*)imageData.getPlanePtr(planeNdx)) + row * rowSize;
518e5c31af7Sopenharmony_ci
519e5c31af7Sopenharmony_ci			deMemcpy(dstPtr, srcPtr, rowSize);
520e5c31af7Sopenharmony_ci		}
521e5c31af7Sopenharmony_ci		flushMappedMemoryRange(vkd, device, allocation->getMemory(), 0u, VK_WHOLE_SIZE);
522e5c31af7Sopenharmony_ci	}
523e5c31af7Sopenharmony_ci
524e5c31af7Sopenharmony_ci	beginCommandBuffer(vkd, *cmdBuffer);
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci	{
527e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier		postCopyBarrier	=
528e5c31af7Sopenharmony_ci		{
529e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
530e5c31af7Sopenharmony_ci			DE_NULL,
531e5c31af7Sopenharmony_ci			0u,
532e5c31af7Sopenharmony_ci			nextAccess,
533e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_PREINITIALIZED,
534e5c31af7Sopenharmony_ci			finalLayout,
535e5c31af7Sopenharmony_ci			VK_QUEUE_FAMILY_IGNORED,
536e5c31af7Sopenharmony_ci			VK_QUEUE_FAMILY_IGNORED,
537e5c31af7Sopenharmony_ci			image,
538e5c31af7Sopenharmony_ci			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, arrayLayer, 1u }
539e5c31af7Sopenharmony_ci		};
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(*cmdBuffer,
542e5c31af7Sopenharmony_ci								(VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT,
543e5c31af7Sopenharmony_ci								(VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
544e5c31af7Sopenharmony_ci								(VkDependencyFlags)0u,
545e5c31af7Sopenharmony_ci								0u,
546e5c31af7Sopenharmony_ci								(const VkMemoryBarrier*)DE_NULL,
547e5c31af7Sopenharmony_ci								0u,
548e5c31af7Sopenharmony_ci								(const VkBufferMemoryBarrier*)DE_NULL,
549e5c31af7Sopenharmony_ci								1u,
550e5c31af7Sopenharmony_ci								&postCopyBarrier);
551e5c31af7Sopenharmony_ci	}
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci	endCommandBuffer(vkd, *cmdBuffer);
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci	submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
556e5c31af7Sopenharmony_ci}
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_civoid downloadImage (const DeviceInterface&	vkd,
559e5c31af7Sopenharmony_ci					VkDevice				device,
560e5c31af7Sopenharmony_ci					deUint32				queueFamilyNdx,
561e5c31af7Sopenharmony_ci					Allocator&				allocator,
562e5c31af7Sopenharmony_ci					VkImage					image,
563e5c31af7Sopenharmony_ci					MultiPlaneImageData*	imageData,
564e5c31af7Sopenharmony_ci					VkAccessFlags			prevAccess,
565e5c31af7Sopenharmony_ci					VkImageLayout			initialLayout,
566e5c31af7Sopenharmony_ci					uint32_t			baseArrayLayer)
567e5c31af7Sopenharmony_ci{
568e5c31af7Sopenharmony_ci	const VkQueue					queue			= getDeviceQueue(vkd, device, queueFamilyNdx, 0u);
569e5c31af7Sopenharmony_ci	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx));
570e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
571e5c31af7Sopenharmony_ci	vector<VkBufferSp>				stagingBuffers;
572e5c31af7Sopenharmony_ci	vector<AllocationSp>			stagingMemory;
573e5c31af7Sopenharmony_ci
574e5c31af7Sopenharmony_ci	const PlanarFormatDescription&	formatDesc		= imageData->getDescription();
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ci	allocateStagingBuffers(vkd, device, allocator, *imageData, &stagingBuffers, &stagingMemory);
577e5c31af7Sopenharmony_ci
578e5c31af7Sopenharmony_ci	beginCommandBuffer(vkd, *cmdBuffer);
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < imageData->getDescription().numPlanes; ++planeNdx)
581e5c31af7Sopenharmony_ci	{
582e5c31af7Sopenharmony_ci		const VkImageAspectFlagBits	aspect	= (formatDesc.numPlanes > 1)
583e5c31af7Sopenharmony_ci											? getPlaneAspect(planeNdx)
584e5c31af7Sopenharmony_ci											: VK_IMAGE_ASPECT_COLOR_BIT;
585e5c31af7Sopenharmony_ci		{
586e5c31af7Sopenharmony_ci			const VkImageMemoryBarrier		preCopyBarrier	=
587e5c31af7Sopenharmony_ci			{
588e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
589e5c31af7Sopenharmony_ci				DE_NULL,
590e5c31af7Sopenharmony_ci				prevAccess,
591e5c31af7Sopenharmony_ci				VK_ACCESS_TRANSFER_READ_BIT,
592e5c31af7Sopenharmony_ci				initialLayout,
593e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
594e5c31af7Sopenharmony_ci				VK_QUEUE_FAMILY_IGNORED,
595e5c31af7Sopenharmony_ci				VK_QUEUE_FAMILY_IGNORED,
596e5c31af7Sopenharmony_ci				image,
597e5c31af7Sopenharmony_ci				{
598e5c31af7Sopenharmony_ci					static_cast<vk::VkImageAspectFlags>(aspect),
599e5c31af7Sopenharmony_ci					0u,
600e5c31af7Sopenharmony_ci					1u,
601e5c31af7Sopenharmony_ci					baseArrayLayer,
602e5c31af7Sopenharmony_ci					1u
603e5c31af7Sopenharmony_ci				}
604e5c31af7Sopenharmony_ci			};
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci			vkd.cmdPipelineBarrier(*cmdBuffer,
607e5c31af7Sopenharmony_ci									(VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
608e5c31af7Sopenharmony_ci									(VkPipelineStageFlags)VK_PIPELINE_STAGE_TRANSFER_BIT,
609e5c31af7Sopenharmony_ci									(VkDependencyFlags)0u,
610e5c31af7Sopenharmony_ci									0u,
611e5c31af7Sopenharmony_ci									(const VkMemoryBarrier*)DE_NULL,
612e5c31af7Sopenharmony_ci									0u,
613e5c31af7Sopenharmony_ci									(const VkBufferMemoryBarrier*)DE_NULL,
614e5c31af7Sopenharmony_ci									1u,
615e5c31af7Sopenharmony_ci									&preCopyBarrier);
616e5c31af7Sopenharmony_ci		}
617e5c31af7Sopenharmony_ci		{
618e5c31af7Sopenharmony_ci			const VkExtent3D imageExtent		= makeExtent3D(imageData->getSize().x(), imageData->getSize().y(), 1u);
619e5c31af7Sopenharmony_ci			const VkExtent3D planeExtent		= getPlaneExtent(formatDesc, imageExtent, planeNdx, 0);
620e5c31af7Sopenharmony_ci			const VkBufferImageCopy		copy	=
621e5c31af7Sopenharmony_ci			{
622e5c31af7Sopenharmony_ci				0u,		// bufferOffset
623e5c31af7Sopenharmony_ci				0u,		// bufferRowLength
624e5c31af7Sopenharmony_ci				0u,		// bufferImageHeight
625e5c31af7Sopenharmony_ci				{ (VkImageAspectFlags)aspect, 0u, baseArrayLayer, 1u },
626e5c31af7Sopenharmony_ci				makeOffset3D(0u, 0u, 0u),
627e5c31af7Sopenharmony_ci				planeExtent
628e5c31af7Sopenharmony_ci			};
629e5c31af7Sopenharmony_ci
630e5c31af7Sopenharmony_ci			vkd.cmdCopyImageToBuffer(*cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **stagingBuffers[planeNdx], 1u, &copy);
631e5c31af7Sopenharmony_ci		}
632e5c31af7Sopenharmony_ci		{
633e5c31af7Sopenharmony_ci			const VkBufferMemoryBarrier		postCopyBarrier	=
634e5c31af7Sopenharmony_ci			{
635e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
636e5c31af7Sopenharmony_ci				DE_NULL,
637e5c31af7Sopenharmony_ci				VK_ACCESS_TRANSFER_WRITE_BIT,
638e5c31af7Sopenharmony_ci				VK_ACCESS_HOST_READ_BIT,
639e5c31af7Sopenharmony_ci				VK_QUEUE_FAMILY_IGNORED,
640e5c31af7Sopenharmony_ci				VK_QUEUE_FAMILY_IGNORED,
641e5c31af7Sopenharmony_ci				**stagingBuffers[planeNdx],
642e5c31af7Sopenharmony_ci				0u,
643e5c31af7Sopenharmony_ci				VK_WHOLE_SIZE
644e5c31af7Sopenharmony_ci			};
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci			vkd.cmdPipelineBarrier(*cmdBuffer,
647e5c31af7Sopenharmony_ci									(VkPipelineStageFlags)VK_PIPELINE_STAGE_TRANSFER_BIT,
648e5c31af7Sopenharmony_ci									(VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT,
649e5c31af7Sopenharmony_ci									(VkDependencyFlags)0u,
650e5c31af7Sopenharmony_ci									0u,
651e5c31af7Sopenharmony_ci									(const VkMemoryBarrier*)DE_NULL,
652e5c31af7Sopenharmony_ci									1u,
653e5c31af7Sopenharmony_ci									&postCopyBarrier,
654e5c31af7Sopenharmony_ci									0u,
655e5c31af7Sopenharmony_ci									(const VkImageMemoryBarrier*)DE_NULL);
656e5c31af7Sopenharmony_ci		}
657e5c31af7Sopenharmony_ci	}
658e5c31af7Sopenharmony_ci
659e5c31af7Sopenharmony_ci	endCommandBuffer(vkd, *cmdBuffer);
660e5c31af7Sopenharmony_ci
661e5c31af7Sopenharmony_ci	submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci	readStagingBuffers(imageData, vkd, device, stagingMemory);
664e5c31af7Sopenharmony_ci}
665e5c31af7Sopenharmony_ci
666e5c31af7Sopenharmony_civoid readImageMemory (const vk::DeviceInterface&							vkd,
667e5c31af7Sopenharmony_ci					  vk::VkDevice											device,
668e5c31af7Sopenharmony_ci					  deUint32												queueFamilyNdx,
669e5c31af7Sopenharmony_ci					  vk::VkImage											image,
670e5c31af7Sopenharmony_ci					  const std::vector<de::SharedPtr<vk::Allocation> >&	allocations,
671e5c31af7Sopenharmony_ci					  MultiPlaneImageData*									imageData,
672e5c31af7Sopenharmony_ci					  vk::VkAccessFlags										prevAccess,
673e5c31af7Sopenharmony_ci					  vk::VkImageLayout										initialLayout)
674e5c31af7Sopenharmony_ci{
675e5c31af7Sopenharmony_ci	const VkQueue					queue			= getDeviceQueue(vkd, device, queueFamilyNdx, 0u);
676e5c31af7Sopenharmony_ci	const Unique<VkCommandPool>		cmdPool			(createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx));
677e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer>	cmdBuffer		(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
678e5c31af7Sopenharmony_ci	const PlanarFormatDescription&	formatDesc		= imageData->getDescription();
679e5c31af7Sopenharmony_ci
680e5c31af7Sopenharmony_ci	beginCommandBuffer(vkd, *cmdBuffer);
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci	{
683e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier		preCopyBarrier	=
684e5c31af7Sopenharmony_ci		{
685e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
686e5c31af7Sopenharmony_ci			DE_NULL,
687e5c31af7Sopenharmony_ci			prevAccess,
688e5c31af7Sopenharmony_ci			vk::VK_ACCESS_HOST_READ_BIT,
689e5c31af7Sopenharmony_ci			initialLayout,
690e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_GENERAL,
691e5c31af7Sopenharmony_ci			VK_QUEUE_FAMILY_IGNORED,
692e5c31af7Sopenharmony_ci			VK_QUEUE_FAMILY_IGNORED,
693e5c31af7Sopenharmony_ci			image,
694e5c31af7Sopenharmony_ci			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
695e5c31af7Sopenharmony_ci		};
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(*cmdBuffer,
698e5c31af7Sopenharmony_ci								(VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
699e5c31af7Sopenharmony_ci								(VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT,
700e5c31af7Sopenharmony_ci								(VkDependencyFlags)0u,
701e5c31af7Sopenharmony_ci								0u,
702e5c31af7Sopenharmony_ci								(const VkMemoryBarrier*)DE_NULL,
703e5c31af7Sopenharmony_ci								0u,
704e5c31af7Sopenharmony_ci								(const VkBufferMemoryBarrier*)DE_NULL,
705e5c31af7Sopenharmony_ci								1u,
706e5c31af7Sopenharmony_ci								&preCopyBarrier);
707e5c31af7Sopenharmony_ci	}
708e5c31af7Sopenharmony_ci
709e5c31af7Sopenharmony_ci	endCommandBuffer(vkd, *cmdBuffer);
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci	submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
712e5c31af7Sopenharmony_ci
713e5c31af7Sopenharmony_ci	for (deUint32 planeNdx = 0; planeNdx < formatDesc.numPlanes; ++planeNdx)
714e5c31af7Sopenharmony_ci	{
715e5c31af7Sopenharmony_ci		const VkImageAspectFlagBits			aspect		= (formatDesc.numPlanes > 1)
716e5c31af7Sopenharmony_ci														? getPlaneAspect(planeNdx)
717e5c31af7Sopenharmony_ci														: VK_IMAGE_ASPECT_COLOR_BIT;
718e5c31af7Sopenharmony_ci		const de::SharedPtr<Allocation>&	allocation	= allocations.size() > 1
719e5c31af7Sopenharmony_ci														? allocations[planeNdx]
720e5c31af7Sopenharmony_ci														: allocations[0];
721e5c31af7Sopenharmony_ci		const size_t						planeSize	= imageData->getPlaneSize(planeNdx);
722e5c31af7Sopenharmony_ci		const deUint32						planeH		= imageData->getSize().y() / formatDesc.planes[planeNdx].heightDivisor;
723e5c31af7Sopenharmony_ci		const VkImageSubresource			subresource	=
724e5c31af7Sopenharmony_ci		{
725e5c31af7Sopenharmony_ci			static_cast<vk::VkImageAspectFlags>(aspect),
726e5c31af7Sopenharmony_ci			0u,
727e5c31af7Sopenharmony_ci			0u,
728e5c31af7Sopenharmony_ci		};
729e5c31af7Sopenharmony_ci		VkSubresourceLayout			layout;
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci		vkd.getImageSubresourceLayout(device, image, &subresource, &layout);
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_ci		invalidateMappedMemoryRange(vkd, device, allocation->getMemory(), 0u, VK_WHOLE_SIZE);
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci		for (deUint32 row = 0; row < planeH; ++row)
736e5c31af7Sopenharmony_ci		{
737e5c31af7Sopenharmony_ci			const size_t		rowSize	= planeSize / planeH;
738e5c31af7Sopenharmony_ci			const void* const	srcPtr	= ((const deUint8*)allocation->getHostPtr()) + layout.offset + layout.rowPitch * row;
739e5c31af7Sopenharmony_ci			void* const			dstPtr	= ((deUint8*)imageData->getPlanePtr(planeNdx)) + row * rowSize;
740e5c31af7Sopenharmony_ci
741e5c31af7Sopenharmony_ci			deMemcpy(dstPtr, srcPtr, rowSize);
742e5c31af7Sopenharmony_ci		}
743e5c31af7Sopenharmony_ci	}
744e5c31af7Sopenharmony_ci}
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci// ChannelAccess utilities
747e5c31af7Sopenharmony_cinamespace
748e5c31af7Sopenharmony_ci{
749e5c31af7Sopenharmony_ci
750e5c31af7Sopenharmony_ci//! Extend < 32b signed integer to 32b
751e5c31af7Sopenharmony_ciinline deInt32 signExtend (deUint32 src, int bits)
752e5c31af7Sopenharmony_ci{
753e5c31af7Sopenharmony_ci	const deUint32 signBit = 1u << (bits-1);
754e5c31af7Sopenharmony_ci
755e5c31af7Sopenharmony_ci	src |= ~((src & signBit) - 1);
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci	return (deInt32)src;
758e5c31af7Sopenharmony_ci}
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_cideUint32 divRoundUp (deUint32 a, deUint32 b)
761e5c31af7Sopenharmony_ci{
762e5c31af7Sopenharmony_ci	if (a % b == 0)
763e5c31af7Sopenharmony_ci		return a / b;
764e5c31af7Sopenharmony_ci	else
765e5c31af7Sopenharmony_ci		return (a / b) + 1;
766e5c31af7Sopenharmony_ci}
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci// \todo Taken from tcuTexture.cpp
769e5c31af7Sopenharmony_ci// \todo [2011-09-21 pyry] Move to tcutil?
770e5c31af7Sopenharmony_citemplate <typename T>
771e5c31af7Sopenharmony_ciinline T convertSatRte (float f)
772e5c31af7Sopenharmony_ci{
773e5c31af7Sopenharmony_ci	// \note Doesn't work for 64-bit types
774e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(sizeof(T) < sizeof(deUint64));
775e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0));
776e5c31af7Sopenharmony_ci
777e5c31af7Sopenharmony_ci	deInt64	minVal	= std::numeric_limits<T>::min();
778e5c31af7Sopenharmony_ci	deInt64 maxVal	= std::numeric_limits<T>::max();
779e5c31af7Sopenharmony_ci	float	q		= deFloatFrac(f);
780e5c31af7Sopenharmony_ci	deInt64 intVal	= (deInt64)(f-q);
781e5c31af7Sopenharmony_ci
782e5c31af7Sopenharmony_ci	// Rounding.
783e5c31af7Sopenharmony_ci	if (q == 0.5f)
784e5c31af7Sopenharmony_ci	{
785e5c31af7Sopenharmony_ci		if (intVal % 2 != 0)
786e5c31af7Sopenharmony_ci			intVal++;
787e5c31af7Sopenharmony_ci	}
788e5c31af7Sopenharmony_ci	else if (q > 0.5f)
789e5c31af7Sopenharmony_ci		intVal++;
790e5c31af7Sopenharmony_ci	// else Don't add anything
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci	// Saturate.
793e5c31af7Sopenharmony_ci	intVal = de::max(minVal, de::min(maxVal, intVal));
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci	return (T)intVal;
796e5c31af7Sopenharmony_ci}
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_ci} // anonymous
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_ciChannelAccess::ChannelAccess (tcu::TextureChannelClass	channelClass,
801e5c31af7Sopenharmony_ci							  deUint8					channelSize,
802e5c31af7Sopenharmony_ci							  const tcu::IVec3&			size,
803e5c31af7Sopenharmony_ci							  const tcu::IVec3&			bitPitch,
804e5c31af7Sopenharmony_ci							  void*						data,
805e5c31af7Sopenharmony_ci							  deUint32					bitOffset)
806e5c31af7Sopenharmony_ci	: m_channelClass	(channelClass)
807e5c31af7Sopenharmony_ci	, m_channelSize		(channelSize)
808e5c31af7Sopenharmony_ci	, m_size			(size)
809e5c31af7Sopenharmony_ci	, m_bitPitch		(bitPitch)
810e5c31af7Sopenharmony_ci	, m_data			((deUint8*)data + (bitOffset / 8))
811e5c31af7Sopenharmony_ci	, m_bitOffset		(bitOffset % 8)
812e5c31af7Sopenharmony_ci{
813e5c31af7Sopenharmony_ci}
814e5c31af7Sopenharmony_ci
815e5c31af7Sopenharmony_cideUint32 ChannelAccess::getChannelUint (const tcu::IVec3& pos) const
816e5c31af7Sopenharmony_ci{
817e5c31af7Sopenharmony_ci	DE_ASSERT(pos[0] < m_size[0]);
818e5c31af7Sopenharmony_ci	DE_ASSERT(pos[1] < m_size[1]);
819e5c31af7Sopenharmony_ci	DE_ASSERT(pos[2] < m_size[2]);
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ci	const deInt32			bitOffset	(m_bitOffset + tcu::dot(m_bitPitch, pos));
822e5c31af7Sopenharmony_ci	const deUint8* const	firstByte	= ((const deUint8*)m_data) + (bitOffset / 8);
823e5c31af7Sopenharmony_ci	const deUint32			byteCount	= divRoundUp((bitOffset + m_channelSize) - 8u * (bitOffset / 8u), 8u);
824e5c31af7Sopenharmony_ci	const deUint32			mask		(m_channelSize == 32u ? ~0x0u : (0x1u << m_channelSize) - 1u);
825e5c31af7Sopenharmony_ci	const deUint32			offset		= bitOffset % 8;
826e5c31af7Sopenharmony_ci	deUint32				bits		= 0u;
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci	deMemcpy(&bits, firstByte, byteCount);
829e5c31af7Sopenharmony_ci
830e5c31af7Sopenharmony_ci	return (bits >> offset) & mask;
831e5c31af7Sopenharmony_ci}
832e5c31af7Sopenharmony_ci
833e5c31af7Sopenharmony_civoid ChannelAccess::setChannel (const tcu::IVec3& pos, deUint32 x)
834e5c31af7Sopenharmony_ci{
835e5c31af7Sopenharmony_ci	DE_ASSERT(pos[0] < m_size[0]);
836e5c31af7Sopenharmony_ci	DE_ASSERT(pos[1] < m_size[1]);
837e5c31af7Sopenharmony_ci	DE_ASSERT(pos[2] < m_size[2]);
838e5c31af7Sopenharmony_ci
839e5c31af7Sopenharmony_ci	const deInt32	bitOffset	(m_bitOffset + tcu::dot(m_bitPitch, pos));
840e5c31af7Sopenharmony_ci	deUint8* const	firstByte	= ((deUint8*)m_data) + (bitOffset / 8);
841e5c31af7Sopenharmony_ci	const deUint32	byteCount	= divRoundUp((bitOffset + m_channelSize) - 8u * (bitOffset / 8u), 8u);
842e5c31af7Sopenharmony_ci	const deUint32	mask		(m_channelSize == 32u ? ~0x0u : (0x1u << m_channelSize) - 1u);
843e5c31af7Sopenharmony_ci	const deUint32	offset		= bitOffset % 8;
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_ci	const deUint32	bits		= (x & mask) << offset;
846e5c31af7Sopenharmony_ci	deUint32		oldBits		= 0;
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_ci	deMemcpy(&oldBits, firstByte, byteCount);
849e5c31af7Sopenharmony_ci
850e5c31af7Sopenharmony_ci	{
851e5c31af7Sopenharmony_ci		const deUint32	newBits	= bits | (oldBits & (~(mask << offset)));
852e5c31af7Sopenharmony_ci
853e5c31af7Sopenharmony_ci		deMemcpy(firstByte, &newBits,  byteCount);
854e5c31af7Sopenharmony_ci	}
855e5c31af7Sopenharmony_ci}
856e5c31af7Sopenharmony_ci
857e5c31af7Sopenharmony_cifloat ChannelAccess::getChannel (const tcu::IVec3& pos) const
858e5c31af7Sopenharmony_ci{
859e5c31af7Sopenharmony_ci	const deUint32	bits	(getChannelUint(pos));
860e5c31af7Sopenharmony_ci
861e5c31af7Sopenharmony_ci	switch (m_channelClass)
862e5c31af7Sopenharmony_ci	{
863e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
864e5c31af7Sopenharmony_ci			return (float)bits / (float)(m_channelSize == 32 ? ~0x0u : ((0x1u << m_channelSize) - 1u));
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
867e5c31af7Sopenharmony_ci			return (float)bits;
868e5c31af7Sopenharmony_ci
869e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
870e5c31af7Sopenharmony_ci			return de::max(-1.0f, (float)signExtend(bits, m_channelSize) / (float)((0x1u << (m_channelSize - 1u)) - 1u));
871e5c31af7Sopenharmony_ci
872e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
873e5c31af7Sopenharmony_ci			return (float)signExtend(bits, m_channelSize);
874e5c31af7Sopenharmony_ci
875e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
876e5c31af7Sopenharmony_ci			if (m_channelSize == 32)
877e5c31af7Sopenharmony_ci				return tcu::Float32(bits).asFloat();
878e5c31af7Sopenharmony_ci			else
879e5c31af7Sopenharmony_ci			{
880e5c31af7Sopenharmony_ci				DE_FATAL("Float type not supported");
881e5c31af7Sopenharmony_ci				return -1.0f;
882e5c31af7Sopenharmony_ci			}
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_ci		default:
885e5c31af7Sopenharmony_ci			DE_FATAL("Unknown texture channel class");
886e5c31af7Sopenharmony_ci			return -1.0f;
887e5c31af7Sopenharmony_ci	}
888e5c31af7Sopenharmony_ci}
889e5c31af7Sopenharmony_ci
890e5c31af7Sopenharmony_citcu::Interval ChannelAccess::getChannel (const tcu::FloatFormat&	conversionFormat,
891e5c31af7Sopenharmony_ci										 const tcu::IVec3&			pos) const
892e5c31af7Sopenharmony_ci{
893e5c31af7Sopenharmony_ci	const deUint32	bits	(getChannelUint(pos));
894e5c31af7Sopenharmony_ci
895e5c31af7Sopenharmony_ci	switch (m_channelClass)
896e5c31af7Sopenharmony_ci	{
897e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
898e5c31af7Sopenharmony_ci			return conversionFormat.roundOut(conversionFormat.roundOut((double)bits, false)
899e5c31af7Sopenharmony_ci											/ conversionFormat.roundOut((double)(m_channelSize == 32 ? ~0x0u : ((0x1u << m_channelSize) - 1u)), false), false);
900e5c31af7Sopenharmony_ci
901e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
902e5c31af7Sopenharmony_ci			return conversionFormat.roundOut((double)bits, false);
903e5c31af7Sopenharmony_ci
904e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
905e5c31af7Sopenharmony_ci		{
906e5c31af7Sopenharmony_ci			const tcu::Interval result (conversionFormat.roundOut(conversionFormat.roundOut((double)signExtend(bits, m_channelSize), false)
907e5c31af7Sopenharmony_ci																/ conversionFormat.roundOut((double)((0x1u << (m_channelSize - 1u)) - 1u), false), false));
908e5c31af7Sopenharmony_ci
909e5c31af7Sopenharmony_ci			return tcu::Interval(de::max(-1.0, result.lo()), de::max(-1.0, result.hi()));
910e5c31af7Sopenharmony_ci		}
911e5c31af7Sopenharmony_ci
912e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
913e5c31af7Sopenharmony_ci			return conversionFormat.roundOut((double)signExtend(bits, m_channelSize), false);
914e5c31af7Sopenharmony_ci
915e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
916e5c31af7Sopenharmony_ci			if (m_channelSize == 32)
917e5c31af7Sopenharmony_ci				return conversionFormat.roundOut(tcu::Float32(bits).asFloat(), false);
918e5c31af7Sopenharmony_ci			else
919e5c31af7Sopenharmony_ci			{
920e5c31af7Sopenharmony_ci				DE_FATAL("Float type not supported");
921e5c31af7Sopenharmony_ci				return tcu::Interval();
922e5c31af7Sopenharmony_ci			}
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ci		default:
925e5c31af7Sopenharmony_ci			DE_FATAL("Unknown texture channel class");
926e5c31af7Sopenharmony_ci			return tcu::Interval();
927e5c31af7Sopenharmony_ci	}
928e5c31af7Sopenharmony_ci}
929e5c31af7Sopenharmony_ci
930e5c31af7Sopenharmony_civoid ChannelAccess::setChannel (const tcu::IVec3& pos, float x)
931e5c31af7Sopenharmony_ci{
932e5c31af7Sopenharmony_ci	DE_ASSERT(pos[0] < m_size[0]);
933e5c31af7Sopenharmony_ci	DE_ASSERT(pos[1] < m_size[1]);
934e5c31af7Sopenharmony_ci	DE_ASSERT(pos[2] < m_size[2]);
935e5c31af7Sopenharmony_ci
936e5c31af7Sopenharmony_ci	const deUint32	mask	(m_channelSize == 32u ? ~0x0u : (0x1u << m_channelSize) - 1u);
937e5c31af7Sopenharmony_ci
938e5c31af7Sopenharmony_ci	switch (m_channelClass)
939e5c31af7Sopenharmony_ci	{
940e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
941e5c31af7Sopenharmony_ci		{
942e5c31af7Sopenharmony_ci			const deUint32	maxValue	(mask);
943e5c31af7Sopenharmony_ci			const deUint32	value		(de::min(maxValue, (deUint32)convertSatRte<deUint32>(x * (float)maxValue)));
944e5c31af7Sopenharmony_ci			setChannel(pos, value);
945e5c31af7Sopenharmony_ci			break;
946e5c31af7Sopenharmony_ci		}
947e5c31af7Sopenharmony_ci
948e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
949e5c31af7Sopenharmony_ci		{
950e5c31af7Sopenharmony_ci			const deInt32	range	((0x1u << (m_channelSize - 1u)) - 1u);
951e5c31af7Sopenharmony_ci			const deUint32	value	((deUint32)de::clamp<deInt32>(convertSatRte<deInt32>(x * (float)range), -range, range));
952e5c31af7Sopenharmony_ci			setChannel(pos, value);
953e5c31af7Sopenharmony_ci			break;
954e5c31af7Sopenharmony_ci		}
955e5c31af7Sopenharmony_ci
956e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
957e5c31af7Sopenharmony_ci		{
958e5c31af7Sopenharmony_ci			const deUint32	maxValue	(mask);
959e5c31af7Sopenharmony_ci			const deUint32	value		(de::min(maxValue, (deUint32)x));
960e5c31af7Sopenharmony_ci			setChannel(pos, value);
961e5c31af7Sopenharmony_ci			break;
962e5c31af7Sopenharmony_ci		}
963e5c31af7Sopenharmony_ci
964e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
965e5c31af7Sopenharmony_ci		{
966e5c31af7Sopenharmony_ci			const deInt32	minValue	(-(deInt32)(1u << (m_channelSize - 1u)));
967e5c31af7Sopenharmony_ci			const deInt32	maxValue	((deInt32)((1u << (m_channelSize - 1u)) - 1u));
968e5c31af7Sopenharmony_ci			const deUint32	value		((deUint32)de::clamp((deInt32)x, minValue, maxValue));
969e5c31af7Sopenharmony_ci			setChannel(pos, value);
970e5c31af7Sopenharmony_ci			break;
971e5c31af7Sopenharmony_ci		}
972e5c31af7Sopenharmony_ci
973e5c31af7Sopenharmony_ci		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
974e5c31af7Sopenharmony_ci		{
975e5c31af7Sopenharmony_ci			if (m_channelSize == 32)
976e5c31af7Sopenharmony_ci			{
977e5c31af7Sopenharmony_ci				const deUint32	value		= tcu::Float32(x).bits();
978e5c31af7Sopenharmony_ci				setChannel(pos, value);
979e5c31af7Sopenharmony_ci			}
980e5c31af7Sopenharmony_ci			else
981e5c31af7Sopenharmony_ci				DE_FATAL("Float type not supported");
982e5c31af7Sopenharmony_ci			break;
983e5c31af7Sopenharmony_ci		}
984e5c31af7Sopenharmony_ci
985e5c31af7Sopenharmony_ci		default:
986e5c31af7Sopenharmony_ci			DE_FATAL("Unknown texture channel class");
987e5c31af7Sopenharmony_ci	}
988e5c31af7Sopenharmony_ci}
989e5c31af7Sopenharmony_ci
990e5c31af7Sopenharmony_ciChannelAccess getChannelAccess (MultiPlaneImageData&				data,
991e5c31af7Sopenharmony_ci								const vk::PlanarFormatDescription&	formatInfo,
992e5c31af7Sopenharmony_ci								const UVec2&						size,
993e5c31af7Sopenharmony_ci								int									channelNdx)
994e5c31af7Sopenharmony_ci{
995e5c31af7Sopenharmony_ci	DE_ASSERT(formatInfo.hasChannelNdx(channelNdx));
996e5c31af7Sopenharmony_ci
997e5c31af7Sopenharmony_ci	const deUint32	planeNdx			= formatInfo.channels[channelNdx].planeNdx;
998e5c31af7Sopenharmony_ci	const deUint32	valueOffsetBits		= formatInfo.channels[channelNdx].offsetBits;
999e5c31af7Sopenharmony_ci	const deUint32	pixelStrideBytes	= formatInfo.channels[channelNdx].strideBytes;
1000e5c31af7Sopenharmony_ci	const deUint32	pixelStrideBits		= pixelStrideBytes * 8;
1001e5c31af7Sopenharmony_ci	const deUint8	sizeBits			= formatInfo.channels[channelNdx].sizeBits;
1002e5c31af7Sopenharmony_ci
1003e5c31af7Sopenharmony_ci	DE_ASSERT(size.x() % (formatInfo.blockWidth * formatInfo.planes[planeNdx].widthDivisor) == 0);
1004e5c31af7Sopenharmony_ci	DE_ASSERT(size.y() % (formatInfo.blockHeight * formatInfo.planes[planeNdx].heightDivisor) == 0);
1005e5c31af7Sopenharmony_ci
1006e5c31af7Sopenharmony_ci	deUint32		accessWidth			= size.x() / ( formatInfo.blockWidth * formatInfo.planes[planeNdx].widthDivisor );
1007e5c31af7Sopenharmony_ci	const deUint32	accessHeight		= size.y() / ( formatInfo.blockHeight * formatInfo.planes[planeNdx].heightDivisor );
1008e5c31af7Sopenharmony_ci	const deUint32	elementSizeBytes	= formatInfo.planes[planeNdx].elementSizeBytes;
1009e5c31af7Sopenharmony_ci	const deUint32	rowPitch			= formatInfo.planes[planeNdx].elementSizeBytes * accessWidth;
1010e5c31af7Sopenharmony_ci	const deUint32	rowPitchBits		= rowPitch * 8;
1011e5c31af7Sopenharmony_ci
1012e5c31af7Sopenharmony_ci	if (pixelStrideBytes != elementSizeBytes)
1013e5c31af7Sopenharmony_ci	{
1014e5c31af7Sopenharmony_ci		DE_ASSERT(elementSizeBytes % pixelStrideBytes == 0);
1015e5c31af7Sopenharmony_ci		accessWidth *= elementSizeBytes/pixelStrideBytes;
1016e5c31af7Sopenharmony_ci	}
1017e5c31af7Sopenharmony_ci
1018e5c31af7Sopenharmony_ci	return ChannelAccess((tcu::TextureChannelClass)formatInfo.channels[channelNdx].type, sizeBits, tcu::IVec3(accessWidth, accessHeight, 1u), tcu::IVec3((int)pixelStrideBits, (int)rowPitchBits, 0), data.getPlanePtr(planeNdx), (deUint32)valueOffsetBits);
1019e5c31af7Sopenharmony_ci}
1020e5c31af7Sopenharmony_ci
1021e5c31af7Sopenharmony_cibool isXChromaSubsampled (vk::VkFormat format)
1022e5c31af7Sopenharmony_ci{
1023e5c31af7Sopenharmony_ci	switch (format)
1024e5c31af7Sopenharmony_ci	{
1025e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8B8G8R8_422_UNORM:
1026e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B8G8R8G8_422_UNORM:
1027e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
1028e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
1029e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
1030e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
1031e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
1032e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
1033e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
1034e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
1035e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
1036e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
1037e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
1038e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
1039e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
1040e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
1041e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
1042e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
1043e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16B16G16R16_422_UNORM:
1044e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B16G16R16G16_422_UNORM:
1045e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
1046e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
1047e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
1048e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
1049e5c31af7Sopenharmony_ci			return true;
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ci		default:
1052e5c31af7Sopenharmony_ci			return false;
1053e5c31af7Sopenharmony_ci	}
1054e5c31af7Sopenharmony_ci}
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_cibool isYChromaSubsampled (vk::VkFormat format)
1057e5c31af7Sopenharmony_ci{
1058e5c31af7Sopenharmony_ci	switch (format)
1059e5c31af7Sopenharmony_ci	{
1060e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
1061e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
1062e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
1063e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
1064e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
1065e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
1066e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
1067e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
1068e5c31af7Sopenharmony_ci			return true;
1069e5c31af7Sopenharmony_ci
1070e5c31af7Sopenharmony_ci		default:
1071e5c31af7Sopenharmony_ci			return false;
1072e5c31af7Sopenharmony_ci	}
1073e5c31af7Sopenharmony_ci}
1074e5c31af7Sopenharmony_ci
1075e5c31af7Sopenharmony_cibool areLsb6BitsDontCare(vk::VkFormat srcFormat, vk::VkFormat dstFormat)
1076e5c31af7Sopenharmony_ci{
1077e5c31af7Sopenharmony_ci	if ((srcFormat == vk::VK_FORMAT_R10X6_UNORM_PACK16)	                        ||
1078e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_R10X6_UNORM_PACK16)                         ||
1079e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16)                   ||
1080e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16)                   ||
1081e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16)         ||
1082e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16)         ||
1083e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16)     ||
1084e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16)     ||
1085e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16)     ||
1086e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16)     ||
1087e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16)  ||
1088e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16)  ||
1089e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16) ||
1090e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16) ||
1091e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16) ||
1092e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16) ||
1093e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16)  ||
1094e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16)  ||
1095e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16) ||
1096e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16))
1097e5c31af7Sopenharmony_ci	{
1098e5c31af7Sopenharmony_ci		return true;
1099e5c31af7Sopenharmony_ci	}
1100e5c31af7Sopenharmony_ci
1101e5c31af7Sopenharmony_ci	return false;
1102e5c31af7Sopenharmony_ci}
1103e5c31af7Sopenharmony_ci
1104e5c31af7Sopenharmony_cibool areLsb4BitsDontCare(vk::VkFormat srcFormat, vk::VkFormat dstFormat)
1105e5c31af7Sopenharmony_ci{
1106e5c31af7Sopenharmony_ci	if ((srcFormat == vk::VK_FORMAT_R12X4_UNORM_PACK16)                         ||
1107e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_R12X4_UNORM_PACK16)                         ||
1108e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16)                   ||
1109e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16)                   ||
1110e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16)         ||
1111e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16)         ||
1112e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16)     ||
1113e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16)     ||
1114e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16)     ||
1115e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16)     ||
1116e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16) ||
1117e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16) ||
1118e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16)  ||
1119e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16)  ||
1120e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16) ||
1121e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16) ||
1122e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16)  ||
1123e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16)  ||
1124e5c31af7Sopenharmony_ci		(srcFormat == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16) ||
1125e5c31af7Sopenharmony_ci		(dstFormat == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16))
1126e5c31af7Sopenharmony_ci	{
1127e5c31af7Sopenharmony_ci		return true;
1128e5c31af7Sopenharmony_ci	}
1129e5c31af7Sopenharmony_ci
1130e5c31af7Sopenharmony_ci	return false;
1131e5c31af7Sopenharmony_ci}
1132e5c31af7Sopenharmony_ci
1133e5c31af7Sopenharmony_ci// \note Used for range expansion
1134e5c31af7Sopenharmony_citcu::UVec4 getYCbCrBitDepth (vk::VkFormat format)
1135e5c31af7Sopenharmony_ci{
1136e5c31af7Sopenharmony_ci	switch (format)
1137e5c31af7Sopenharmony_ci	{
1138e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8B8G8R8_422_UNORM:
1139e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B8G8R8G8_422_UNORM:
1140e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
1141e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
1142e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
1143e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
1144e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
1145e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT:
1146e5c31af7Sopenharmony_ci			return tcu::UVec4(8, 8, 8, 0);
1147e5c31af7Sopenharmony_ci
1148e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R10X6_UNORM_PACK16:
1149e5c31af7Sopenharmony_ci			return tcu::UVec4(10, 0, 0, 0);
1150e5c31af7Sopenharmony_ci
1151e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
1152e5c31af7Sopenharmony_ci			return tcu::UVec4(10, 10, 0, 0);
1153e5c31af7Sopenharmony_ci
1154e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
1155e5c31af7Sopenharmony_ci			return tcu::UVec4(10, 10, 10, 10);
1156e5c31af7Sopenharmony_ci
1157e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
1158e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
1159e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
1160e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
1161e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
1162e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
1163e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
1164e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:
1165e5c31af7Sopenharmony_ci			return tcu::UVec4(10, 10, 10, 0);
1166e5c31af7Sopenharmony_ci
1167e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R12X4_UNORM_PACK16:
1168e5c31af7Sopenharmony_ci			return tcu::UVec4(12, 0, 0, 0);
1169e5c31af7Sopenharmony_ci
1170e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
1171e5c31af7Sopenharmony_ci			return tcu::UVec4(12, 12, 0, 0);
1172e5c31af7Sopenharmony_ci
1173e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
1174e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
1175e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
1176e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
1177e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
1178e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
1179e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
1180e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
1181e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:
1182e5c31af7Sopenharmony_ci			return tcu::UVec4(12, 12, 12, 12);
1183e5c31af7Sopenharmony_ci
1184e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16B16G16R16_422_UNORM:
1185e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B16G16R16G16_422_UNORM:
1186e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
1187e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
1188e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
1189e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
1190e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
1191e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT:
1192e5c31af7Sopenharmony_ci			return tcu::UVec4(16, 16, 16, 0);
1193e5c31af7Sopenharmony_ci
1194e5c31af7Sopenharmony_ci		default:
1195e5c31af7Sopenharmony_ci			return tcu::getTextureFormatBitDepth(vk::mapVkFormat(format)).cast<deUint32>();
1196e5c31af7Sopenharmony_ci	}
1197e5c31af7Sopenharmony_ci}
1198e5c31af7Sopenharmony_ci
1199e5c31af7Sopenharmony_cistd::vector<tcu::FloatFormat> getPrecision (VkFormat format)
1200e5c31af7Sopenharmony_ci{
1201e5c31af7Sopenharmony_ci	std::vector<FloatFormat>	floatFormats;
1202e5c31af7Sopenharmony_ci	UVec4						channelDepth	= getYCbCrBitDepth (format);
1203e5c31af7Sopenharmony_ci
1204e5c31af7Sopenharmony_ci	for (deUint32 channelIdx = 0; channelIdx < 4; channelIdx++)
1205e5c31af7Sopenharmony_ci		floatFormats.push_back(tcu::FloatFormat(0, 0, channelDepth[channelIdx], false, tcu::YES));
1206e5c31af7Sopenharmony_ci
1207e5c31af7Sopenharmony_ci	return floatFormats;
1208e5c31af7Sopenharmony_ci}
1209e5c31af7Sopenharmony_ci
1210e5c31af7Sopenharmony_cideUint32 getYCbCrFormatChannelCount (vk::VkFormat format)
1211e5c31af7Sopenharmony_ci{
1212e5c31af7Sopenharmony_ci	switch (format)
1213e5c31af7Sopenharmony_ci	{
1214e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16:
1215e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32:
1216e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32:
1217e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32:
1218e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16:
1219e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16:
1220e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B8G8R8A8_UNORM:
1221e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
1222e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
1223e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R16G16B16A16_UNORM:
1224e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16:
1225e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16:
1226e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R8G8B8A8_UNORM:
1227e5c31af7Sopenharmony_ci			return 4;
1228e5c31af7Sopenharmony_ci
1229e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
1230e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
1231e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B16G16R16G16_422_UNORM:
1232e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B5G6R5_UNORM_PACK16:
1233e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B8G8R8G8_422_UNORM:
1234e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_B8G8R8_UNORM:
1235e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
1236e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
1237e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
1238e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:
1239e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
1240e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
1241e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
1242e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
1243e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
1244e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
1245e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:
1246e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
1247e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
1248e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
1249e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16B16G16R16_422_UNORM:
1250e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
1251e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
1252e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT:
1253e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
1254e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
1255e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
1256e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8B8G8R8_422_UNORM:
1257e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
1258e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
1259e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT:
1260e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
1261e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
1262e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
1263e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R16G16B16_UNORM:
1264e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R5G6B5_UNORM_PACK16:
1265e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R8G8B8_UNORM:
1266e5c31af7Sopenharmony_ci			return 3;
1267e5c31af7Sopenharmony_ci
1268e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
1269e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
1270e5c31af7Sopenharmony_ci			return 2;
1271e5c31af7Sopenharmony_ci
1272e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R10X6_UNORM_PACK16:
1273e5c31af7Sopenharmony_ci		case vk::VK_FORMAT_R12X4_UNORM_PACK16:
1274e5c31af7Sopenharmony_ci			return 1;
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_ci		default:
1277e5c31af7Sopenharmony_ci			DE_FATAL("Unknown number of channels");
1278e5c31af7Sopenharmony_ci			return -1;
1279e5c31af7Sopenharmony_ci	}
1280e5c31af7Sopenharmony_ci}
1281e5c31af7Sopenharmony_ci
1282e5c31af7Sopenharmony_ci// YCbCr color conversion utilities
1283e5c31af7Sopenharmony_cinamespace
1284e5c31af7Sopenharmony_ci{
1285e5c31af7Sopenharmony_ci
1286e5c31af7Sopenharmony_citcu::Interval rangeExpandChroma (vk::VkSamplerYcbcrRange		range,
1287e5c31af7Sopenharmony_ci								 const tcu::FloatFormat&		conversionFormat,
1288e5c31af7Sopenharmony_ci								 const deUint32					bits,
1289e5c31af7Sopenharmony_ci								 const tcu::Interval&			sample)
1290e5c31af7Sopenharmony_ci{
1291e5c31af7Sopenharmony_ci	const deUint32	values	(0x1u << bits);
1292e5c31af7Sopenharmony_ci
1293e5c31af7Sopenharmony_ci	switch (range)
1294e5c31af7Sopenharmony_ci	{
1295e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
1296e5c31af7Sopenharmony_ci			return conversionFormat.roundOut(sample - conversionFormat.roundOut(tcu::Interval((double)(0x1u << (bits - 1u)) / (double)((0x1u << bits) - 1u)), false), false);
1297e5c31af7Sopenharmony_ci
1298e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
1299e5c31af7Sopenharmony_ci		{
1300e5c31af7Sopenharmony_ci			const tcu::Interval	a			(conversionFormat.roundOut(sample * tcu::Interval((double)(values - 1u)), false));
1301e5c31af7Sopenharmony_ci			const tcu::Interval	dividend	(conversionFormat.roundOut(a - tcu::Interval((double)(128u * (0x1u << (bits - 8u)))), false));
1302e5c31af7Sopenharmony_ci			const tcu::Interval	divisor		((double)(224u * (0x1u << (bits - 8u))));
1303e5c31af7Sopenharmony_ci			const tcu::Interval	result		(conversionFormat.roundOut(dividend / divisor, false));
1304e5c31af7Sopenharmony_ci
1305e5c31af7Sopenharmony_ci			return result;
1306e5c31af7Sopenharmony_ci		}
1307e5c31af7Sopenharmony_ci
1308e5c31af7Sopenharmony_ci		default:
1309e5c31af7Sopenharmony_ci			DE_FATAL("Unknown YCbCrRange");
1310e5c31af7Sopenharmony_ci			return tcu::Interval();
1311e5c31af7Sopenharmony_ci	}
1312e5c31af7Sopenharmony_ci}
1313e5c31af7Sopenharmony_ci
1314e5c31af7Sopenharmony_citcu::Interval rangeExpandLuma (vk::VkSamplerYcbcrRange		range,
1315e5c31af7Sopenharmony_ci							   const tcu::FloatFormat&		conversionFormat,
1316e5c31af7Sopenharmony_ci							   const deUint32				bits,
1317e5c31af7Sopenharmony_ci							   const tcu::Interval&			sample)
1318e5c31af7Sopenharmony_ci{
1319e5c31af7Sopenharmony_ci	const deUint32	values	(0x1u << bits);
1320e5c31af7Sopenharmony_ci
1321e5c31af7Sopenharmony_ci	switch (range)
1322e5c31af7Sopenharmony_ci	{
1323e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
1324e5c31af7Sopenharmony_ci			return conversionFormat.roundOut(sample, false);
1325e5c31af7Sopenharmony_ci
1326e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
1327e5c31af7Sopenharmony_ci		{
1328e5c31af7Sopenharmony_ci			const tcu::Interval	a			(conversionFormat.roundOut(sample * tcu::Interval((double)(values - 1u)), false));
1329e5c31af7Sopenharmony_ci			const tcu::Interval	dividend	(conversionFormat.roundOut(a - tcu::Interval((double)(16u * (0x1u << (bits - 8u)))), false));
1330e5c31af7Sopenharmony_ci			const tcu::Interval	divisor		((double)(219u * (0x1u << (bits - 8u))));
1331e5c31af7Sopenharmony_ci			const tcu::Interval	result		(conversionFormat.roundOut(dividend / divisor, false));
1332e5c31af7Sopenharmony_ci
1333e5c31af7Sopenharmony_ci			return result;
1334e5c31af7Sopenharmony_ci		}
1335e5c31af7Sopenharmony_ci
1336e5c31af7Sopenharmony_ci		default:
1337e5c31af7Sopenharmony_ci			DE_FATAL("Unknown YCbCrRange");
1338e5c31af7Sopenharmony_ci			return tcu::Interval();
1339e5c31af7Sopenharmony_ci	}
1340e5c31af7Sopenharmony_ci}
1341e5c31af7Sopenharmony_ci
1342e5c31af7Sopenharmony_citcu::Interval clampMaybe (const tcu::Interval&	x,
1343e5c31af7Sopenharmony_ci						  double				min,
1344e5c31af7Sopenharmony_ci						  double				max)
1345e5c31af7Sopenharmony_ci{
1346e5c31af7Sopenharmony_ci	tcu::Interval result = x;
1347e5c31af7Sopenharmony_ci
1348e5c31af7Sopenharmony_ci	DE_ASSERT(min <= max);
1349e5c31af7Sopenharmony_ci
1350e5c31af7Sopenharmony_ci	if (x.lo() < min)
1351e5c31af7Sopenharmony_ci		result = result | tcu::Interval(min);
1352e5c31af7Sopenharmony_ci
1353e5c31af7Sopenharmony_ci	if (x.hi() > max)
1354e5c31af7Sopenharmony_ci		result = result | tcu::Interval(max);
1355e5c31af7Sopenharmony_ci
1356e5c31af7Sopenharmony_ci	return result;
1357e5c31af7Sopenharmony_ci}
1358e5c31af7Sopenharmony_ci
1359e5c31af7Sopenharmony_civoid convertColor (vk::VkSamplerYcbcrModelConversion	colorModel,
1360e5c31af7Sopenharmony_ci				   vk::VkSamplerYcbcrRange				range,
1361e5c31af7Sopenharmony_ci				   const vector<tcu::FloatFormat>&		conversionFormat,
1362e5c31af7Sopenharmony_ci				   const tcu::UVec4&					bitDepth,
1363e5c31af7Sopenharmony_ci				   const tcu::Interval					input[4],
1364e5c31af7Sopenharmony_ci				   tcu::Interval						output[4])
1365e5c31af7Sopenharmony_ci{
1366e5c31af7Sopenharmony_ci	switch (colorModel)
1367e5c31af7Sopenharmony_ci	{
1368e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY:
1369e5c31af7Sopenharmony_ci		{
1370e5c31af7Sopenharmony_ci			for (size_t ndx = 0; ndx < 4; ndx++)
1371e5c31af7Sopenharmony_ci				output[ndx] = input[ndx];
1372e5c31af7Sopenharmony_ci			break;
1373e5c31af7Sopenharmony_ci		}
1374e5c31af7Sopenharmony_ci
1375e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
1376e5c31af7Sopenharmony_ci		{
1377e5c31af7Sopenharmony_ci			output[0] = clampMaybe(rangeExpandChroma(range, conversionFormat[0], bitDepth[0], input[0]), -0.5, 0.5);
1378e5c31af7Sopenharmony_ci			output[1] = clampMaybe(rangeExpandLuma(range, conversionFormat[1], bitDepth[1], input[1]), 0.0, 1.0);
1379e5c31af7Sopenharmony_ci			output[2] = clampMaybe(rangeExpandChroma(range, conversionFormat[2], bitDepth[2], input[2]), -0.5, 0.5);
1380e5c31af7Sopenharmony_ci			output[3] = input[3];
1381e5c31af7Sopenharmony_ci			break;
1382e5c31af7Sopenharmony_ci		}
1383e5c31af7Sopenharmony_ci
1384e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601:
1385e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709:
1386e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020:
1387e5c31af7Sopenharmony_ci		{
1388e5c31af7Sopenharmony_ci			const tcu::Interval	y			(rangeExpandLuma(range, conversionFormat[1], bitDepth[1], input[1]));
1389e5c31af7Sopenharmony_ci			const tcu::Interval	cr			(rangeExpandChroma(range, conversionFormat[0], bitDepth[0], input[0]));
1390e5c31af7Sopenharmony_ci			const tcu::Interval	cb			(rangeExpandChroma(range, conversionFormat[2], bitDepth[2], input[2]));
1391e5c31af7Sopenharmony_ci
1392e5c31af7Sopenharmony_ci			const tcu::Interval	yClamped	(clampMaybe(y,   0.0, 1.0));
1393e5c31af7Sopenharmony_ci			const tcu::Interval	crClamped	(clampMaybe(cr, -0.5, 0.5));
1394e5c31af7Sopenharmony_ci			const tcu::Interval	cbClamped	(clampMaybe(cb, -0.5, 0.5));
1395e5c31af7Sopenharmony_ci
1396e5c31af7Sopenharmony_ci			if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601)
1397e5c31af7Sopenharmony_ci			{
1398e5c31af7Sopenharmony_ci				output[0] = conversionFormat[0].roundOut(yClamped + conversionFormat[0].roundOut(1.402 * crClamped, false), false);
1399e5c31af7Sopenharmony_ci				output[1] = conversionFormat[1].roundOut(conversionFormat[1].roundOut(yClamped - conversionFormat[1].roundOut((0.202008 / 0.587) * cbClamped, false), false) - conversionFormat[1].roundOut((0.419198 / 0.587) * crClamped, false), false);
1400e5c31af7Sopenharmony_ci				output[2] = conversionFormat[2].roundOut(yClamped + conversionFormat[2].roundOut(1.772 * cbClamped, false), false);
1401e5c31af7Sopenharmony_ci			}
1402e5c31af7Sopenharmony_ci			else if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709)
1403e5c31af7Sopenharmony_ci			{
1404e5c31af7Sopenharmony_ci				output[0] = conversionFormat[0].roundOut(yClamped + conversionFormat[0].roundOut(1.5748 * crClamped, false), false);
1405e5c31af7Sopenharmony_ci				output[1] = conversionFormat[1].roundOut(conversionFormat[1].roundOut(yClamped - conversionFormat[1].roundOut((0.13397432 / 0.7152) * cbClamped, false), false) - conversionFormat[1].roundOut((0.33480248 / 0.7152) * crClamped, false), false);
1406e5c31af7Sopenharmony_ci				output[2] = conversionFormat[2].roundOut(yClamped + conversionFormat[2].roundOut(1.8556 * cbClamped, false), false);
1407e5c31af7Sopenharmony_ci			}
1408e5c31af7Sopenharmony_ci			else
1409e5c31af7Sopenharmony_ci			{
1410e5c31af7Sopenharmony_ci				output[0] = conversionFormat[0].roundOut(yClamped + conversionFormat[0].roundOut(1.4746 * crClamped, false), false);
1411e5c31af7Sopenharmony_ci				output[1] = conversionFormat[1].roundOut(conversionFormat[1].roundOut(yClamped - conversionFormat[1].roundOut(conversionFormat[1].roundOut(0.11156702 / 0.6780, false) * cbClamped, false), false) - conversionFormat[1].roundOut(conversionFormat[1].roundOut(0.38737742 / 0.6780, false) * crClamped, false), false);
1412e5c31af7Sopenharmony_ci				output[2] = conversionFormat[2].roundOut(yClamped + conversionFormat[2].roundOut(1.8814 * cbClamped, false), false);
1413e5c31af7Sopenharmony_ci			}
1414e5c31af7Sopenharmony_ci			output[3] = input[3];
1415e5c31af7Sopenharmony_ci			break;
1416e5c31af7Sopenharmony_ci		}
1417e5c31af7Sopenharmony_ci
1418e5c31af7Sopenharmony_ci		default:
1419e5c31af7Sopenharmony_ci			DE_FATAL("Unknown YCbCrModel");
1420e5c31af7Sopenharmony_ci	}
1421e5c31af7Sopenharmony_ci
1422e5c31af7Sopenharmony_ci	if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY)
1423e5c31af7Sopenharmony_ci	{
1424e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < 3; ndx++)
1425e5c31af7Sopenharmony_ci			output[ndx] = clampMaybe(output[ndx], 0.0, 1.0);
1426e5c31af7Sopenharmony_ci	}
1427e5c31af7Sopenharmony_ci}
1428e5c31af7Sopenharmony_ci
1429e5c31af7Sopenharmony_ciint mirror (int coord)
1430e5c31af7Sopenharmony_ci{
1431e5c31af7Sopenharmony_ci	return coord >= 0 ? coord : -(1 + coord);
1432e5c31af7Sopenharmony_ci}
1433e5c31af7Sopenharmony_ci
1434e5c31af7Sopenharmony_ciint imod (int a, int b)
1435e5c31af7Sopenharmony_ci{
1436e5c31af7Sopenharmony_ci	int m = a % b;
1437e5c31af7Sopenharmony_ci	return m < 0 ? m + b : m;
1438e5c31af7Sopenharmony_ci}
1439e5c31af7Sopenharmony_ci
1440e5c31af7Sopenharmony_citcu::Interval frac (const tcu::Interval& x)
1441e5c31af7Sopenharmony_ci{
1442e5c31af7Sopenharmony_ci	if (x.hi() - x.lo() >= 1.0)
1443e5c31af7Sopenharmony_ci		return tcu::Interval(0.0, 1.0);
1444e5c31af7Sopenharmony_ci	else
1445e5c31af7Sopenharmony_ci	{
1446e5c31af7Sopenharmony_ci		const tcu::Interval ret (deFrac(x.lo()), deFrac(x.hi()));
1447e5c31af7Sopenharmony_ci
1448e5c31af7Sopenharmony_ci		return ret;
1449e5c31af7Sopenharmony_ci	}
1450e5c31af7Sopenharmony_ci}
1451e5c31af7Sopenharmony_ci
1452e5c31af7Sopenharmony_citcu::Interval calculateUV (const tcu::FloatFormat&	coordFormat,
1453e5c31af7Sopenharmony_ci						   const tcu::Interval&		st,
1454e5c31af7Sopenharmony_ci						   const int				size)
1455e5c31af7Sopenharmony_ci{
1456e5c31af7Sopenharmony_ci	return coordFormat.roundOut(coordFormat.roundOut(st, false) * tcu::Interval((double)size), false);
1457e5c31af7Sopenharmony_ci}
1458e5c31af7Sopenharmony_ci
1459e5c31af7Sopenharmony_citcu::IVec2 calculateNearestIJRange (const tcu::FloatFormat&	coordFormat,
1460e5c31af7Sopenharmony_ci								    const tcu::Interval&	uv)
1461e5c31af7Sopenharmony_ci{
1462e5c31af7Sopenharmony_ci	const tcu::Interval	ij	(coordFormat.roundOut(coordFormat.roundOut(uv, false) - tcu::Interval(0.5), false));
1463e5c31af7Sopenharmony_ci
1464e5c31af7Sopenharmony_ci	return tcu::IVec2(deRoundToInt32(ij.lo() - coordFormat.ulp(ij.lo(), 1)), deRoundToInt32(ij.hi() + coordFormat.ulp(ij.hi(), 1)));
1465e5c31af7Sopenharmony_ci}
1466e5c31af7Sopenharmony_ci
1467e5c31af7Sopenharmony_ci// Calculate range of pixel coordinates that can be used as lower coordinate for linear sampling
1468e5c31af7Sopenharmony_citcu::IVec2 calculateLinearIJRange (const tcu::FloatFormat&	coordFormat,
1469e5c31af7Sopenharmony_ci								   const tcu::Interval&		uv)
1470e5c31af7Sopenharmony_ci{
1471e5c31af7Sopenharmony_ci	const tcu::Interval	ij	(coordFormat.roundOut(uv - tcu::Interval(0.5), false));
1472e5c31af7Sopenharmony_ci
1473e5c31af7Sopenharmony_ci	return tcu::IVec2(deFloorToInt32(ij.lo()), deFloorToInt32(ij.hi()));
1474e5c31af7Sopenharmony_ci}
1475e5c31af7Sopenharmony_ci
1476e5c31af7Sopenharmony_citcu::IVec2 calculateIJRange (vk::VkFilter				filter,
1477e5c31af7Sopenharmony_ci							 const tcu::FloatFormat&	coordFormat,
1478e5c31af7Sopenharmony_ci							 const tcu::Interval&		uv)
1479e5c31af7Sopenharmony_ci{
1480e5c31af7Sopenharmony_ci	DE_ASSERT(filter == vk::VK_FILTER_NEAREST || filter == vk::VK_FILTER_LINEAR);
1481e5c31af7Sopenharmony_ci	return (filter == vk::VK_FILTER_LINEAR)	? calculateLinearIJRange(coordFormat, uv)
1482e5c31af7Sopenharmony_ci											: calculateNearestIJRange(coordFormat, uv);
1483e5c31af7Sopenharmony_ci}
1484e5c31af7Sopenharmony_ci
1485e5c31af7Sopenharmony_citcu::Interval calculateAB (const deUint32		subTexelPrecisionBits,
1486e5c31af7Sopenharmony_ci						   const tcu::Interval&	uv,
1487e5c31af7Sopenharmony_ci						   int					ij)
1488e5c31af7Sopenharmony_ci{
1489e5c31af7Sopenharmony_ci	const deUint32		subdivisions	= 0x1u << subTexelPrecisionBits;
1490e5c31af7Sopenharmony_ci	const tcu::Interval	ab				(frac((uv - 0.5) & tcu::Interval((double)ij, (double)(ij + 1))));
1491e5c31af7Sopenharmony_ci	const tcu::Interval	gridAB			(ab * tcu::Interval(subdivisions));
1492e5c31af7Sopenharmony_ci	const tcu::Interval	rounded			(de::max(deFloor(gridAB.lo()) / subdivisions, 0.0) , de::min(deCeil(gridAB.hi()) / subdivisions, 1.0));
1493e5c31af7Sopenharmony_ci
1494e5c31af7Sopenharmony_ci	return rounded;
1495e5c31af7Sopenharmony_ci}
1496e5c31af7Sopenharmony_ci
1497e5c31af7Sopenharmony_citcu::Interval lookupWrapped (const ChannelAccess&		access,
1498e5c31af7Sopenharmony_ci							 const tcu::FloatFormat&	conversionFormat,
1499e5c31af7Sopenharmony_ci							 vk::VkSamplerAddressMode	addressModeU,
1500e5c31af7Sopenharmony_ci							 vk::VkSamplerAddressMode	addressModeV,
1501e5c31af7Sopenharmony_ci							 const tcu::IVec2&			coord)
1502e5c31af7Sopenharmony_ci{
1503e5c31af7Sopenharmony_ci	return access.getChannel(conversionFormat,
1504e5c31af7Sopenharmony_ci							 tcu::IVec3(wrap(addressModeU, coord.x(), access.getSize().x()), wrap(addressModeV, coord.y(), access.getSize().y()), 0));
1505e5c31af7Sopenharmony_ci}
1506e5c31af7Sopenharmony_ci
1507e5c31af7Sopenharmony_citcu::Interval linearInterpolate (const tcu::FloatFormat&	filteringFormat,
1508e5c31af7Sopenharmony_ci								 const tcu::Interval&		a,
1509e5c31af7Sopenharmony_ci								 const tcu::Interval&		b,
1510e5c31af7Sopenharmony_ci								 const tcu::Interval&		p00,
1511e5c31af7Sopenharmony_ci								 const tcu::Interval&		p10,
1512e5c31af7Sopenharmony_ci								 const tcu::Interval&		p01,
1513e5c31af7Sopenharmony_ci								 const tcu::Interval&		p11)
1514e5c31af7Sopenharmony_ci{
1515e5c31af7Sopenharmony_ci	const tcu::Interval	p[4] =
1516e5c31af7Sopenharmony_ci	{
1517e5c31af7Sopenharmony_ci		p00,
1518e5c31af7Sopenharmony_ci		p10,
1519e5c31af7Sopenharmony_ci		p01,
1520e5c31af7Sopenharmony_ci		p11
1521e5c31af7Sopenharmony_ci	};
1522e5c31af7Sopenharmony_ci	tcu::Interval		result	(0.0);
1523e5c31af7Sopenharmony_ci
1524e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < 4; ndx++)
1525e5c31af7Sopenharmony_ci	{
1526e5c31af7Sopenharmony_ci		const tcu::Interval	weightA	(filteringFormat.roundOut((ndx % 2) == 0 ? (1.0 - a) : a, false));
1527e5c31af7Sopenharmony_ci		const tcu::Interval	weightB	(filteringFormat.roundOut((ndx / 2) == 0 ? (1.0 - b) : b, false));
1528e5c31af7Sopenharmony_ci		const tcu::Interval	weight	(filteringFormat.roundOut(weightA * weightB, false));
1529e5c31af7Sopenharmony_ci
1530e5c31af7Sopenharmony_ci		result = filteringFormat.roundOut(result + filteringFormat.roundOut(p[ndx] * weight, false), false);
1531e5c31af7Sopenharmony_ci	}
1532e5c31af7Sopenharmony_ci
1533e5c31af7Sopenharmony_ci	return result;
1534e5c31af7Sopenharmony_ci}
1535e5c31af7Sopenharmony_ci
1536e5c31af7Sopenharmony_citcu::Interval calculateImplicitChromaUV (const tcu::FloatFormat&	coordFormat,
1537e5c31af7Sopenharmony_ci										 vk::VkChromaLocation		offset,
1538e5c31af7Sopenharmony_ci										 const tcu::Interval&		uv)
1539e5c31af7Sopenharmony_ci{
1540e5c31af7Sopenharmony_ci	if (offset == vk::VK_CHROMA_LOCATION_COSITED_EVEN)
1541e5c31af7Sopenharmony_ci		return coordFormat.roundOut(0.5 * coordFormat.roundOut(uv + 0.5, false), false);
1542e5c31af7Sopenharmony_ci	else
1543e5c31af7Sopenharmony_ci		return coordFormat.roundOut(0.5 * uv, false);
1544e5c31af7Sopenharmony_ci}
1545e5c31af7Sopenharmony_ci
1546e5c31af7Sopenharmony_citcu::Interval linearSample (const ChannelAccess&		access,
1547e5c31af7Sopenharmony_ci						    const tcu::FloatFormat&		conversionFormat,
1548e5c31af7Sopenharmony_ci						    const tcu::FloatFormat&		filteringFormat,
1549e5c31af7Sopenharmony_ci						    vk::VkSamplerAddressMode	addressModeU,
1550e5c31af7Sopenharmony_ci						    vk::VkSamplerAddressMode	addressModeV,
1551e5c31af7Sopenharmony_ci						    const tcu::IVec2&			coord,
1552e5c31af7Sopenharmony_ci						    const tcu::Interval&		a,
1553e5c31af7Sopenharmony_ci						    const tcu::Interval&		b)
1554e5c31af7Sopenharmony_ci{
1555e5c31af7Sopenharmony_ci	return linearInterpolate(filteringFormat, a, b,
1556e5c31af7Sopenharmony_ci									lookupWrapped(access, conversionFormat, addressModeU, addressModeV, coord + tcu::IVec2(0, 0)),
1557e5c31af7Sopenharmony_ci									lookupWrapped(access, conversionFormat, addressModeU, addressModeV, coord + tcu::IVec2(1, 0)),
1558e5c31af7Sopenharmony_ci									lookupWrapped(access, conversionFormat, addressModeU, addressModeV, coord + tcu::IVec2(0, 1)),
1559e5c31af7Sopenharmony_ci									lookupWrapped(access, conversionFormat, addressModeU, addressModeV, coord + tcu::IVec2(1, 1)));
1560e5c31af7Sopenharmony_ci}
1561e5c31af7Sopenharmony_ci
1562e5c31af7Sopenharmony_citcu::Interval reconstructLinearXChromaSample (const tcu::FloatFormat&	filteringFormat,
1563e5c31af7Sopenharmony_ci											  const tcu::FloatFormat&	conversionFormat,
1564e5c31af7Sopenharmony_ci											  vk::VkChromaLocation		offset,
1565e5c31af7Sopenharmony_ci											  vk::VkSamplerAddressMode	addressModeU,
1566e5c31af7Sopenharmony_ci											  vk::VkSamplerAddressMode	addressModeV,
1567e5c31af7Sopenharmony_ci											  const ChannelAccess&		access,
1568e5c31af7Sopenharmony_ci											  int						i,
1569e5c31af7Sopenharmony_ci											  int						j)
1570e5c31af7Sopenharmony_ci{
1571e5c31af7Sopenharmony_ci	const int subI	= offset == vk::VK_CHROMA_LOCATION_COSITED_EVEN
1572e5c31af7Sopenharmony_ci					? divFloor(i, 2)
1573e5c31af7Sopenharmony_ci					: (i % 2 == 0 ? divFloor(i, 2) - 1 : divFloor(i, 2));
1574e5c31af7Sopenharmony_ci	const double a	= offset == vk::VK_CHROMA_LOCATION_COSITED_EVEN
1575e5c31af7Sopenharmony_ci					? (i % 2 == 0 ? 0.0 : 0.5)
1576e5c31af7Sopenharmony_ci					: (i % 2 == 0 ? 0.25 : 0.75);
1577e5c31af7Sopenharmony_ci
1578e5c31af7Sopenharmony_ci	const tcu::Interval A (filteringFormat.roundOut(       a  * lookupWrapped(access, conversionFormat, addressModeU, addressModeV, tcu::IVec2(subI, j)), false));
1579e5c31af7Sopenharmony_ci	const tcu::Interval B (filteringFormat.roundOut((1.0 - a) * lookupWrapped(access, conversionFormat, addressModeU, addressModeV, tcu::IVec2(subI + 1, j)), false));
1580e5c31af7Sopenharmony_ci	return filteringFormat.roundOut(A + B, false);
1581e5c31af7Sopenharmony_ci}
1582e5c31af7Sopenharmony_ci
1583e5c31af7Sopenharmony_citcu::Interval reconstructLinearXYChromaSample (const tcu::FloatFormat&	filteringFormat,
1584e5c31af7Sopenharmony_ci										  const tcu::FloatFormat&		conversionFormat,
1585e5c31af7Sopenharmony_ci										  vk::VkChromaLocation			xOffset,
1586e5c31af7Sopenharmony_ci										  vk::VkChromaLocation			yOffset,
1587e5c31af7Sopenharmony_ci										  vk::VkSamplerAddressMode		addressModeU,
1588e5c31af7Sopenharmony_ci										  vk::VkSamplerAddressMode		addressModeV,
1589e5c31af7Sopenharmony_ci										  const ChannelAccess&			access,
1590e5c31af7Sopenharmony_ci										  int							i,
1591e5c31af7Sopenharmony_ci										  int							j)
1592e5c31af7Sopenharmony_ci{
1593e5c31af7Sopenharmony_ci	const int		subI	= xOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN
1594e5c31af7Sopenharmony_ci							? divFloor(i, 2)
1595e5c31af7Sopenharmony_ci							: (i % 2 == 0 ? divFloor(i, 2) - 1 : divFloor(i, 2));
1596e5c31af7Sopenharmony_ci	const int		subJ	= yOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN
1597e5c31af7Sopenharmony_ci							? divFloor(j, 2)
1598e5c31af7Sopenharmony_ci							: (j % 2 == 0 ? divFloor(j, 2) - 1 : divFloor(j, 2));
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci	const double	a		= xOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN
1601e5c31af7Sopenharmony_ci							? (i % 2 == 0 ? 0.0 : 0.5)
1602e5c31af7Sopenharmony_ci							: (i % 2 == 0 ? 0.25 : 0.75);
1603e5c31af7Sopenharmony_ci	const double	b		= yOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN
1604e5c31af7Sopenharmony_ci							? (j % 2 == 0 ? 0.0 : 0.5)
1605e5c31af7Sopenharmony_ci							: (j % 2 == 0 ? 0.25 : 0.75);
1606e5c31af7Sopenharmony_ci
1607e5c31af7Sopenharmony_ci	return linearSample(access, conversionFormat, filteringFormat, addressModeU, addressModeV, tcu::IVec2(subI, subJ), a, b);
1608e5c31af7Sopenharmony_ci}
1609e5c31af7Sopenharmony_ci
1610e5c31af7Sopenharmony_ciconst ChannelAccess& swizzle (vk::VkComponentSwizzle	swizzle,
1611e5c31af7Sopenharmony_ci							  const ChannelAccess&		identityPlane,
1612e5c31af7Sopenharmony_ci							  const ChannelAccess&		rPlane,
1613e5c31af7Sopenharmony_ci							  const ChannelAccess&		gPlane,
1614e5c31af7Sopenharmony_ci							  const ChannelAccess&		bPlane,
1615e5c31af7Sopenharmony_ci							  const ChannelAccess&		aPlane)
1616e5c31af7Sopenharmony_ci{
1617e5c31af7Sopenharmony_ci	switch (swizzle)
1618e5c31af7Sopenharmony_ci	{
1619e5c31af7Sopenharmony_ci		case vk::VK_COMPONENT_SWIZZLE_IDENTITY:	return identityPlane;
1620e5c31af7Sopenharmony_ci		case vk::VK_COMPONENT_SWIZZLE_R:		return rPlane;
1621e5c31af7Sopenharmony_ci		case vk::VK_COMPONENT_SWIZZLE_G:		return gPlane;
1622e5c31af7Sopenharmony_ci		case vk::VK_COMPONENT_SWIZZLE_B:		return bPlane;
1623e5c31af7Sopenharmony_ci		case vk::VK_COMPONENT_SWIZZLE_A:		return aPlane;
1624e5c31af7Sopenharmony_ci
1625e5c31af7Sopenharmony_ci		default:
1626e5c31af7Sopenharmony_ci			DE_FATAL("Unsupported swizzle");
1627e5c31af7Sopenharmony_ci			return identityPlane;
1628e5c31af7Sopenharmony_ci	}
1629e5c31af7Sopenharmony_ci}
1630e5c31af7Sopenharmony_ci
1631e5c31af7Sopenharmony_ci} // anonymous
1632e5c31af7Sopenharmony_ci
1633e5c31af7Sopenharmony_ciint wrap (vk::VkSamplerAddressMode	addressMode,
1634e5c31af7Sopenharmony_ci		  int						coord,
1635e5c31af7Sopenharmony_ci		  int						size)
1636e5c31af7Sopenharmony_ci{
1637e5c31af7Sopenharmony_ci	switch (addressMode)
1638e5c31af7Sopenharmony_ci	{
1639e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
1640e5c31af7Sopenharmony_ci			return (size - 1) - mirror(imod(coord, 2 * size) - size);
1641e5c31af7Sopenharmony_ci
1642e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_ADDRESS_MODE_REPEAT:
1643e5c31af7Sopenharmony_ci			return imod(coord, size);
1644e5c31af7Sopenharmony_ci
1645e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1646e5c31af7Sopenharmony_ci			return de::clamp(coord, 0, size - 1);
1647e5c31af7Sopenharmony_ci
1648e5c31af7Sopenharmony_ci		case vk::VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
1649e5c31af7Sopenharmony_ci			return de::clamp(mirror(coord), 0, size - 1);
1650e5c31af7Sopenharmony_ci
1651e5c31af7Sopenharmony_ci		default:
1652e5c31af7Sopenharmony_ci			DE_FATAL("Unknown wrap mode");
1653e5c31af7Sopenharmony_ci			return ~0;
1654e5c31af7Sopenharmony_ci	}
1655e5c31af7Sopenharmony_ci}
1656e5c31af7Sopenharmony_ci
1657e5c31af7Sopenharmony_ciint divFloor (int a, int b)
1658e5c31af7Sopenharmony_ci{
1659e5c31af7Sopenharmony_ci	if (a % b == 0)
1660e5c31af7Sopenharmony_ci		return a / b;
1661e5c31af7Sopenharmony_ci	else if (a > 0)
1662e5c31af7Sopenharmony_ci		return a / b;
1663e5c31af7Sopenharmony_ci	else
1664e5c31af7Sopenharmony_ci		return (a / b) - 1;
1665e5c31af7Sopenharmony_ci}
1666e5c31af7Sopenharmony_ci
1667e5c31af7Sopenharmony_civoid calculateBounds (const ChannelAccess&				rPlane,
1668e5c31af7Sopenharmony_ci					  const ChannelAccess&				gPlane,
1669e5c31af7Sopenharmony_ci					  const ChannelAccess&				bPlane,
1670e5c31af7Sopenharmony_ci					  const ChannelAccess&				aPlane,
1671e5c31af7Sopenharmony_ci					  const UVec4&						bitDepth,
1672e5c31af7Sopenharmony_ci					  const vector<Vec2>&				sts,
1673e5c31af7Sopenharmony_ci					  const vector<FloatFormat>&		filteringFormat,
1674e5c31af7Sopenharmony_ci					  const vector<FloatFormat>&		conversionFormat,
1675e5c31af7Sopenharmony_ci					  const deUint32					subTexelPrecisionBits,
1676e5c31af7Sopenharmony_ci					  vk::VkFilter						filter,
1677e5c31af7Sopenharmony_ci					  vk::VkSamplerYcbcrModelConversion	colorModel,
1678e5c31af7Sopenharmony_ci					  vk::VkSamplerYcbcrRange			range,
1679e5c31af7Sopenharmony_ci					  vk::VkFilter						chromaFilter,
1680e5c31af7Sopenharmony_ci					  vk::VkChromaLocation				xChromaOffset,
1681e5c31af7Sopenharmony_ci					  vk::VkChromaLocation				yChromaOffset,
1682e5c31af7Sopenharmony_ci					  const vk::VkComponentMapping&		componentMapping,
1683e5c31af7Sopenharmony_ci					  bool								explicitReconstruction,
1684e5c31af7Sopenharmony_ci					  vk::VkSamplerAddressMode			addressModeU,
1685e5c31af7Sopenharmony_ci					  vk::VkSamplerAddressMode			addressModeV,
1686e5c31af7Sopenharmony_ci					  std::vector<Vec4>&				minBounds,
1687e5c31af7Sopenharmony_ci					  std::vector<Vec4>&				maxBounds,
1688e5c31af7Sopenharmony_ci					  std::vector<Vec4>&				uvBounds,
1689e5c31af7Sopenharmony_ci					  std::vector<IVec4>&				ijBounds)
1690e5c31af7Sopenharmony_ci{
1691e5c31af7Sopenharmony_ci	const FloatFormat		highp			(-126, 127, 23, true,
1692e5c31af7Sopenharmony_ci											 tcu::MAYBE,	// subnormals
1693e5c31af7Sopenharmony_ci											 tcu::YES,		// infinities
1694e5c31af7Sopenharmony_ci											 tcu::MAYBE);	// NaN
1695e5c31af7Sopenharmony_ci	const FloatFormat		coordFormat		(-32, 32, 16, true);
1696e5c31af7Sopenharmony_ci	const ChannelAccess&	rAccess			(swizzle(componentMapping.r, rPlane, rPlane, gPlane, bPlane, aPlane));
1697e5c31af7Sopenharmony_ci	const ChannelAccess&	gAccess			(swizzle(componentMapping.g, gPlane, rPlane, gPlane, bPlane, aPlane));
1698e5c31af7Sopenharmony_ci	const ChannelAccess&	bAccess			(swizzle(componentMapping.b, bPlane, rPlane, gPlane, bPlane, aPlane));
1699e5c31af7Sopenharmony_ci	const ChannelAccess&	aAccess			(swizzle(componentMapping.a, aPlane, rPlane, gPlane, bPlane, aPlane));
1700e5c31af7Sopenharmony_ci
1701e5c31af7Sopenharmony_ci	const bool				subsampledX		= gAccess.getSize().x() > rAccess.getSize().x();
1702e5c31af7Sopenharmony_ci	const bool				subsampledY		= gAccess.getSize().y() > rAccess.getSize().y();
1703e5c31af7Sopenharmony_ci
1704e5c31af7Sopenharmony_ci	minBounds.resize(sts.size(), Vec4(TCU_INFINITY));
1705e5c31af7Sopenharmony_ci	maxBounds.resize(sts.size(), Vec4(-TCU_INFINITY));
1706e5c31af7Sopenharmony_ci
1707e5c31af7Sopenharmony_ci	uvBounds.resize(sts.size(), Vec4(TCU_INFINITY, -TCU_INFINITY, TCU_INFINITY, -TCU_INFINITY));
1708e5c31af7Sopenharmony_ci	ijBounds.resize(sts.size(), IVec4(0x7FFFFFFF, -1 -0x7FFFFFFF, 0x7FFFFFFF, -1 -0x7FFFFFFF));
1709e5c31af7Sopenharmony_ci
1710e5c31af7Sopenharmony_ci	// Chroma plane sizes must match
1711e5c31af7Sopenharmony_ci	DE_ASSERT(rAccess.getSize() == bAccess.getSize());
1712e5c31af7Sopenharmony_ci
1713e5c31af7Sopenharmony_ci	// Luma plane sizes must match
1714e5c31af7Sopenharmony_ci	DE_ASSERT(gAccess.getSize() == aAccess.getSize());
1715e5c31af7Sopenharmony_ci
1716e5c31af7Sopenharmony_ci	// Luma plane size must match chroma plane or be twice as big
1717e5c31af7Sopenharmony_ci	DE_ASSERT(rAccess.getSize().x() == gAccess.getSize().x() || 2 * rAccess.getSize().x() == gAccess.getSize().x());
1718e5c31af7Sopenharmony_ci	DE_ASSERT(rAccess.getSize().y() == gAccess.getSize().y() || 2 * rAccess.getSize().y() == gAccess.getSize().y());
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_ci	DE_ASSERT(filter == vk::VK_FILTER_NEAREST || filter == vk::VK_FILTER_LINEAR);
1721e5c31af7Sopenharmony_ci	DE_ASSERT(chromaFilter == vk::VK_FILTER_NEAREST || chromaFilter == vk::VK_FILTER_LINEAR);
1722e5c31af7Sopenharmony_ci	DE_ASSERT(subsampledX || !subsampledY);
1723e5c31af7Sopenharmony_ci
1724e5c31af7Sopenharmony_ci
1725e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < sts.size(); ndx++)
1726e5c31af7Sopenharmony_ci	{
1727e5c31af7Sopenharmony_ci		const Vec2	st		(sts[ndx]);
1728e5c31af7Sopenharmony_ci		Interval	bounds[4];
1729e5c31af7Sopenharmony_ci
1730e5c31af7Sopenharmony_ci		const Interval	u	(calculateUV(coordFormat, st[0], gAccess.getSize().x()));
1731e5c31af7Sopenharmony_ci		const Interval	v	(calculateUV(coordFormat, st[1], gAccess.getSize().y()));
1732e5c31af7Sopenharmony_ci
1733e5c31af7Sopenharmony_ci		uvBounds[ndx][0] = (float)u.lo();
1734e5c31af7Sopenharmony_ci		uvBounds[ndx][1] = (float)u.hi();
1735e5c31af7Sopenharmony_ci
1736e5c31af7Sopenharmony_ci		uvBounds[ndx][2] = (float)v.lo();
1737e5c31af7Sopenharmony_ci		uvBounds[ndx][3] = (float)v.hi();
1738e5c31af7Sopenharmony_ci
1739e5c31af7Sopenharmony_ci		const IVec2	iRange	(calculateIJRange(filter, coordFormat, u));
1740e5c31af7Sopenharmony_ci		const IVec2	jRange	(calculateIJRange(filter, coordFormat, v));
1741e5c31af7Sopenharmony_ci
1742e5c31af7Sopenharmony_ci		ijBounds[ndx][0] = iRange[0];
1743e5c31af7Sopenharmony_ci		ijBounds[ndx][1] = iRange[1];
1744e5c31af7Sopenharmony_ci
1745e5c31af7Sopenharmony_ci		ijBounds[ndx][2] = jRange[0];
1746e5c31af7Sopenharmony_ci		ijBounds[ndx][3] = jRange[1];
1747e5c31af7Sopenharmony_ci
1748e5c31af7Sopenharmony_ci		for (int j = jRange.x(); j <= jRange.y(); j++)
1749e5c31af7Sopenharmony_ci		for (int i = iRange.x(); i <= iRange.y(); i++)
1750e5c31af7Sopenharmony_ci		{
1751e5c31af7Sopenharmony_ci			if (filter == vk::VK_FILTER_NEAREST)
1752e5c31af7Sopenharmony_ci			{
1753e5c31af7Sopenharmony_ci				const Interval	gValue	(lookupWrapped(gAccess, conversionFormat[1], addressModeU, addressModeV, IVec2(i, j)));
1754e5c31af7Sopenharmony_ci				const Interval	aValue	(lookupWrapped(aAccess, conversionFormat[3], addressModeU, addressModeV, IVec2(i, j)));
1755e5c31af7Sopenharmony_ci
1756e5c31af7Sopenharmony_ci				if (explicitReconstruction || !(subsampledX || subsampledY))
1757e5c31af7Sopenharmony_ci				{
1758e5c31af7Sopenharmony_ci					Interval rValue, bValue;
1759e5c31af7Sopenharmony_ci					if (chromaFilter == vk::VK_FILTER_NEAREST || !subsampledX)
1760e5c31af7Sopenharmony_ci					{
1761e5c31af7Sopenharmony_ci						// Reconstruct using nearest if needed, otherwise, just take what's already there.
1762e5c31af7Sopenharmony_ci						const int subI = subsampledX ? i / 2 : i;
1763e5c31af7Sopenharmony_ci						const int subJ = subsampledY ? j / 2 : j;
1764e5c31af7Sopenharmony_ci						rValue = lookupWrapped(rAccess, conversionFormat[0], addressModeU, addressModeV, IVec2(subI, subJ));
1765e5c31af7Sopenharmony_ci						bValue = lookupWrapped(bAccess, conversionFormat[2], addressModeU, addressModeV, IVec2(subI, subJ));
1766e5c31af7Sopenharmony_ci					}
1767e5c31af7Sopenharmony_ci					else // vk::VK_FILTER_LINEAR
1768e5c31af7Sopenharmony_ci					{
1769e5c31af7Sopenharmony_ci						if (subsampledY)
1770e5c31af7Sopenharmony_ci						{
1771e5c31af7Sopenharmony_ci							rValue = reconstructLinearXYChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, yChromaOffset, addressModeU, addressModeV, rAccess, i, j);
1772e5c31af7Sopenharmony_ci							bValue = reconstructLinearXYChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, yChromaOffset, addressModeU, addressModeV, bAccess, i, j);
1773e5c31af7Sopenharmony_ci						}
1774e5c31af7Sopenharmony_ci						else
1775e5c31af7Sopenharmony_ci						{
1776e5c31af7Sopenharmony_ci							rValue = reconstructLinearXChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, addressModeU, addressModeV, rAccess, i, j);
1777e5c31af7Sopenharmony_ci							bValue = reconstructLinearXChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, addressModeU, addressModeV, bAccess, i, j);
1778e5c31af7Sopenharmony_ci						}
1779e5c31af7Sopenharmony_ci					}
1780e5c31af7Sopenharmony_ci
1781e5c31af7Sopenharmony_ci					const Interval srcColor[] =
1782e5c31af7Sopenharmony_ci					{
1783e5c31af7Sopenharmony_ci						rValue,
1784e5c31af7Sopenharmony_ci						gValue,
1785e5c31af7Sopenharmony_ci						bValue,
1786e5c31af7Sopenharmony_ci						aValue
1787e5c31af7Sopenharmony_ci					};
1788e5c31af7Sopenharmony_ci					Interval dstColor[4];
1789e5c31af7Sopenharmony_ci
1790e5c31af7Sopenharmony_ci					convertColor(colorModel, range, conversionFormat, bitDepth, srcColor, dstColor);
1791e5c31af7Sopenharmony_ci
1792e5c31af7Sopenharmony_ci					for (size_t compNdx = 0; compNdx < 4; compNdx++)
1793e5c31af7Sopenharmony_ci						bounds[compNdx] |= highp.roundOut(dstColor[compNdx], false);
1794e5c31af7Sopenharmony_ci				}
1795e5c31af7Sopenharmony_ci				else
1796e5c31af7Sopenharmony_ci				{
1797e5c31af7Sopenharmony_ci					const Interval	chromaU	(subsampledX ? calculateImplicitChromaUV(coordFormat, xChromaOffset, u) : u);
1798e5c31af7Sopenharmony_ci					const Interval	chromaV	(subsampledY ? calculateImplicitChromaUV(coordFormat, yChromaOffset, v) : v);
1799e5c31af7Sopenharmony_ci
1800e5c31af7Sopenharmony_ci					// Reconstructed chroma samples with implicit filtering
1801e5c31af7Sopenharmony_ci					const IVec2	chromaIRange	(subsampledX ? calculateIJRange(chromaFilter, coordFormat, chromaU) : IVec2(i, i));
1802e5c31af7Sopenharmony_ci					const IVec2	chromaJRange	(subsampledY ? calculateIJRange(chromaFilter, coordFormat, chromaV) : IVec2(j, j));
1803e5c31af7Sopenharmony_ci
1804e5c31af7Sopenharmony_ci					for (int chromaJ = chromaJRange.x(); chromaJ <= chromaJRange.y(); chromaJ++)
1805e5c31af7Sopenharmony_ci					for (int chromaI = chromaIRange.x(); chromaI <= chromaIRange.y(); chromaI++)
1806e5c31af7Sopenharmony_ci					{
1807e5c31af7Sopenharmony_ci						Interval rValue, bValue;
1808e5c31af7Sopenharmony_ci
1809e5c31af7Sopenharmony_ci						if (chromaFilter == vk::VK_FILTER_NEAREST)
1810e5c31af7Sopenharmony_ci						{
1811e5c31af7Sopenharmony_ci							rValue = lookupWrapped(rAccess, conversionFormat[0], addressModeU, addressModeV, IVec2(chromaI, chromaJ));
1812e5c31af7Sopenharmony_ci							bValue = lookupWrapped(bAccess, conversionFormat[2], addressModeU, addressModeV, IVec2(chromaI, chromaJ));
1813e5c31af7Sopenharmony_ci						}
1814e5c31af7Sopenharmony_ci						else // vk::VK_FILTER_LINEAR
1815e5c31af7Sopenharmony_ci						{
1816e5c31af7Sopenharmony_ci							const Interval	chromaA	(calculateAB(subTexelPrecisionBits, chromaU, chromaI));
1817e5c31af7Sopenharmony_ci							const Interval	chromaB	(calculateAB(subTexelPrecisionBits, chromaV, chromaJ));
1818e5c31af7Sopenharmony_ci
1819e5c31af7Sopenharmony_ci							rValue = linearSample(rAccess, conversionFormat[0], filteringFormat[0], addressModeU, addressModeV, IVec2(chromaI, chromaJ), chromaA, chromaB);
1820e5c31af7Sopenharmony_ci							bValue = linearSample(bAccess, conversionFormat[2], filteringFormat[2], addressModeU, addressModeV, IVec2(chromaI, chromaJ), chromaA, chromaB);
1821e5c31af7Sopenharmony_ci						}
1822e5c31af7Sopenharmony_ci
1823e5c31af7Sopenharmony_ci						const Interval	srcColor[]	=
1824e5c31af7Sopenharmony_ci						{
1825e5c31af7Sopenharmony_ci							rValue,
1826e5c31af7Sopenharmony_ci							gValue,
1827e5c31af7Sopenharmony_ci							bValue,
1828e5c31af7Sopenharmony_ci							aValue
1829e5c31af7Sopenharmony_ci						};
1830e5c31af7Sopenharmony_ci
1831e5c31af7Sopenharmony_ci						Interval dstColor[4];
1832e5c31af7Sopenharmony_ci						convertColor(colorModel, range, conversionFormat, bitDepth, srcColor, dstColor);
1833e5c31af7Sopenharmony_ci
1834e5c31af7Sopenharmony_ci						for (size_t compNdx = 0; compNdx < 4; compNdx++)
1835e5c31af7Sopenharmony_ci							bounds[compNdx] |= highp.roundOut(dstColor[compNdx], false);
1836e5c31af7Sopenharmony_ci					}
1837e5c31af7Sopenharmony_ci				}
1838e5c31af7Sopenharmony_ci			}
1839e5c31af7Sopenharmony_ci			else // filter == vk::VK_FILTER_LINEAR
1840e5c31af7Sopenharmony_ci			{
1841e5c31af7Sopenharmony_ci				const Interval	lumaA		(calculateAB(subTexelPrecisionBits, u, i));
1842e5c31af7Sopenharmony_ci				const Interval	lumaB		(calculateAB(subTexelPrecisionBits, v, j));
1843e5c31af7Sopenharmony_ci
1844e5c31af7Sopenharmony_ci				const Interval	gValue		(linearSample(gAccess, conversionFormat[1], filteringFormat[1], addressModeU, addressModeV, IVec2(i, j), lumaA, lumaB));
1845e5c31af7Sopenharmony_ci				const Interval	aValue		(linearSample(aAccess, conversionFormat[3], filteringFormat[3], addressModeU, addressModeV, IVec2(i, j), lumaA, lumaB));
1846e5c31af7Sopenharmony_ci
1847e5c31af7Sopenharmony_ci				if (explicitReconstruction || !(subsampledX || subsampledY))
1848e5c31af7Sopenharmony_ci				{
1849e5c31af7Sopenharmony_ci					Interval rValue, bValue;
1850e5c31af7Sopenharmony_ci					if (chromaFilter == vk::VK_FILTER_NEAREST || !subsampledX)
1851e5c31af7Sopenharmony_ci					{
1852e5c31af7Sopenharmony_ci						rValue = linearInterpolate(filteringFormat[0], lumaA, lumaB,
1853e5c31af7Sopenharmony_ci													lookupWrapped(rAccess, conversionFormat[0], addressModeU, addressModeV, IVec2(i       / (subsampledX ? 2 : 1), j       / (subsampledY ? 2 : 1))),
1854e5c31af7Sopenharmony_ci													lookupWrapped(rAccess, conversionFormat[0], addressModeU, addressModeV, IVec2((i + 1) / (subsampledX ? 2 : 1), j       / (subsampledY ? 2 : 1))),
1855e5c31af7Sopenharmony_ci													lookupWrapped(rAccess, conversionFormat[0], addressModeU, addressModeV, IVec2(i       / (subsampledX ? 2 : 1), (j + 1) / (subsampledY ? 2 : 1))),
1856e5c31af7Sopenharmony_ci													lookupWrapped(rAccess, conversionFormat[0], addressModeU, addressModeV, IVec2((i + 1) / (subsampledX ? 2 : 1), (j + 1) / (subsampledY ? 2 : 1))));
1857e5c31af7Sopenharmony_ci						bValue = linearInterpolate(filteringFormat[2], lumaA, lumaB,
1858e5c31af7Sopenharmony_ci													lookupWrapped(bAccess, conversionFormat[2], addressModeU, addressModeV, IVec2(i       / (subsampledX ? 2 : 1), j       / (subsampledY ? 2 : 1))),
1859e5c31af7Sopenharmony_ci													lookupWrapped(bAccess, conversionFormat[2], addressModeU, addressModeV, IVec2((i + 1) / (subsampledX ? 2 : 1), j       / (subsampledY ? 2 : 1))),
1860e5c31af7Sopenharmony_ci													lookupWrapped(bAccess, conversionFormat[2], addressModeU, addressModeV, IVec2(i       / (subsampledX ? 2 : 1), (j + 1) / (subsampledY ? 2 : 1))),
1861e5c31af7Sopenharmony_ci													lookupWrapped(bAccess, conversionFormat[2], addressModeU, addressModeV, IVec2((i + 1) / (subsampledX ? 2 : 1), (j + 1) / (subsampledY ? 2 : 1))));
1862e5c31af7Sopenharmony_ci					}
1863e5c31af7Sopenharmony_ci					else // vk::VK_FILTER_LINEAR
1864e5c31af7Sopenharmony_ci					{
1865e5c31af7Sopenharmony_ci						if (subsampledY)
1866e5c31af7Sopenharmony_ci						{
1867e5c31af7Sopenharmony_ci							// Linear, Reconstructed xx chroma samples with explicit linear filtering
1868e5c31af7Sopenharmony_ci							rValue = linearInterpolate(filteringFormat[0], lumaA, lumaB,
1869e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, yChromaOffset, addressModeU, addressModeV, rAccess, i, j),
1870e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, yChromaOffset, addressModeU, addressModeV, rAccess, i + 1, j),
1871e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, yChromaOffset, addressModeU, addressModeV, rAccess, i , j + 1),
1872e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, yChromaOffset, addressModeU, addressModeV, rAccess, i + 1, j + 1));
1873e5c31af7Sopenharmony_ci							bValue = linearInterpolate(filteringFormat[2], lumaA, lumaB,
1874e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, yChromaOffset, addressModeU, addressModeV, bAccess, i, j),
1875e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, yChromaOffset, addressModeU, addressModeV, bAccess, i + 1, j),
1876e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, yChromaOffset, addressModeU, addressModeV, bAccess, i , j + 1),
1877e5c31af7Sopenharmony_ci														reconstructLinearXYChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, yChromaOffset, addressModeU, addressModeV, bAccess, i + 1, j + 1));
1878e5c31af7Sopenharmony_ci						}
1879e5c31af7Sopenharmony_ci						else
1880e5c31af7Sopenharmony_ci						{
1881e5c31af7Sopenharmony_ci							// Linear, Reconstructed x chroma samples with explicit linear filtering
1882e5c31af7Sopenharmony_ci							rValue = linearInterpolate(filteringFormat[0], lumaA, lumaB,
1883e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, addressModeU, addressModeV, rAccess, i, j),
1884e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, addressModeU, addressModeV, rAccess, i + 1, j),
1885e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, addressModeU, addressModeV, rAccess, i , j + 1),
1886e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[0], conversionFormat[0], xChromaOffset, addressModeU, addressModeV, rAccess, i + 1, j + 1));
1887e5c31af7Sopenharmony_ci							bValue = linearInterpolate(filteringFormat[2], lumaA, lumaB,
1888e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, addressModeU, addressModeV, bAccess, i, j),
1889e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, addressModeU, addressModeV, bAccess, i + 1, j),
1890e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, addressModeU, addressModeV, bAccess, i , j + 1),
1891e5c31af7Sopenharmony_ci														reconstructLinearXChromaSample(filteringFormat[2], conversionFormat[2], xChromaOffset, addressModeU, addressModeV, bAccess, i + 1, j + 1));
1892e5c31af7Sopenharmony_ci						}
1893e5c31af7Sopenharmony_ci					}
1894e5c31af7Sopenharmony_ci
1895e5c31af7Sopenharmony_ci					const Interval	srcColor[]	=
1896e5c31af7Sopenharmony_ci					{
1897e5c31af7Sopenharmony_ci						rValue,
1898e5c31af7Sopenharmony_ci						gValue,
1899e5c31af7Sopenharmony_ci						bValue,
1900e5c31af7Sopenharmony_ci						aValue
1901e5c31af7Sopenharmony_ci					};
1902e5c31af7Sopenharmony_ci					Interval dstColor[4];
1903e5c31af7Sopenharmony_ci
1904e5c31af7Sopenharmony_ci					convertColor(colorModel, range, conversionFormat, bitDepth, srcColor, dstColor);
1905e5c31af7Sopenharmony_ci
1906e5c31af7Sopenharmony_ci					for (size_t compNdx = 0; compNdx < 4; compNdx++)
1907e5c31af7Sopenharmony_ci						bounds[compNdx] |= highp.roundOut(dstColor[compNdx], false);
1908e5c31af7Sopenharmony_ci				}
1909e5c31af7Sopenharmony_ci				else
1910e5c31af7Sopenharmony_ci				{
1911e5c31af7Sopenharmony_ci					const Interval	chromaU	(subsampledX ? calculateImplicitChromaUV(coordFormat, xChromaOffset, u) : u);
1912e5c31af7Sopenharmony_ci					const Interval	chromaV	(subsampledY ? calculateImplicitChromaUV(coordFormat, yChromaOffset, v) : v);
1913e5c31af7Sopenharmony_ci
1914e5c31af7Sopenharmony_ci					// TODO: It looks incorrect to ignore the chroma filter here. Is it?
1915e5c31af7Sopenharmony_ci					const IVec2	chromaIRange	(calculateNearestIJRange(coordFormat, chromaU));
1916e5c31af7Sopenharmony_ci					const IVec2	chromaJRange	(calculateNearestIJRange(coordFormat, chromaV));
1917e5c31af7Sopenharmony_ci
1918e5c31af7Sopenharmony_ci					for (int chromaJ = chromaJRange.x(); chromaJ <= chromaJRange.y(); chromaJ++)
1919e5c31af7Sopenharmony_ci					for (int chromaI = chromaIRange.x(); chromaI <= chromaIRange.y(); chromaI++)
1920e5c31af7Sopenharmony_ci					{
1921e5c31af7Sopenharmony_ci						Interval rValue, bValue;
1922e5c31af7Sopenharmony_ci
1923e5c31af7Sopenharmony_ci						if (chromaFilter == vk::VK_FILTER_NEAREST)
1924e5c31af7Sopenharmony_ci						{
1925e5c31af7Sopenharmony_ci							rValue = lookupWrapped(rAccess, conversionFormat[1], addressModeU, addressModeV, IVec2(chromaI, chromaJ));
1926e5c31af7Sopenharmony_ci							bValue = lookupWrapped(bAccess, conversionFormat[3], addressModeU, addressModeV, IVec2(chromaI, chromaJ));
1927e5c31af7Sopenharmony_ci						}
1928e5c31af7Sopenharmony_ci						else // vk::VK_FILTER_LINEAR
1929e5c31af7Sopenharmony_ci						{
1930e5c31af7Sopenharmony_ci							const Interval	chromaA	(calculateAB(subTexelPrecisionBits, chromaU, chromaI));
1931e5c31af7Sopenharmony_ci							const Interval	chromaB	(calculateAB(subTexelPrecisionBits, chromaV, chromaJ));
1932e5c31af7Sopenharmony_ci
1933e5c31af7Sopenharmony_ci							rValue = linearSample(rAccess, conversionFormat[0], filteringFormat[0], addressModeU, addressModeV, IVec2(chromaI, chromaJ), chromaA, chromaB);
1934e5c31af7Sopenharmony_ci							bValue = linearSample(bAccess, conversionFormat[2], filteringFormat[2], addressModeU, addressModeV, IVec2(chromaI, chromaJ), chromaA, chromaB);
1935e5c31af7Sopenharmony_ci						}
1936e5c31af7Sopenharmony_ci
1937e5c31af7Sopenharmony_ci						const Interval	srcColor[]	=
1938e5c31af7Sopenharmony_ci						{
1939e5c31af7Sopenharmony_ci							rValue,
1940e5c31af7Sopenharmony_ci							gValue,
1941e5c31af7Sopenharmony_ci							bValue,
1942e5c31af7Sopenharmony_ci							aValue
1943e5c31af7Sopenharmony_ci						};
1944e5c31af7Sopenharmony_ci						Interval dstColor[4];
1945e5c31af7Sopenharmony_ci						convertColor(colorModel, range, conversionFormat, bitDepth, srcColor, dstColor);
1946e5c31af7Sopenharmony_ci
1947e5c31af7Sopenharmony_ci						for (size_t compNdx = 0; compNdx < 4; compNdx++)
1948e5c31af7Sopenharmony_ci							bounds[compNdx] |= highp.roundOut(dstColor[compNdx], false);
1949e5c31af7Sopenharmony_ci					}
1950e5c31af7Sopenharmony_ci				}
1951e5c31af7Sopenharmony_ci			}
1952e5c31af7Sopenharmony_ci		}
1953e5c31af7Sopenharmony_ci
1954e5c31af7Sopenharmony_ci		minBounds[ndx] = Vec4((float)bounds[0].lo(), (float)bounds[1].lo(), (float)bounds[2].lo(), (float)bounds[3].lo());
1955e5c31af7Sopenharmony_ci		maxBounds[ndx] = Vec4((float)bounds[0].hi(), (float)bounds[1].hi(), (float)bounds[2].hi(), (float)bounds[3].hi());
1956e5c31af7Sopenharmony_ci	}
1957e5c31af7Sopenharmony_ci}
1958e5c31af7Sopenharmony_ci
1959e5c31af7Sopenharmony_ci} // ycbcr
1960e5c31af7Sopenharmony_ci
1961e5c31af7Sopenharmony_ci} // vkt
1962