1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Android Open Source Project
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 Image load/store Tests
23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "vktImageLoadStoreTests.hpp"
26e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp"
27e5c31af7Sopenharmony_ci#include "vktImageTestsUtil.hpp"
28e5c31af7Sopenharmony_ci#include "vktImageLoadStoreUtil.hpp"
29e5c31af7Sopenharmony_ci#include "vktImageTexture.hpp"
30e5c31af7Sopenharmony_ci
31e5c31af7Sopenharmony_ci#include "vkDefs.hpp"
32e5c31af7Sopenharmony_ci#include "vkRef.hpp"
33e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
34e5c31af7Sopenharmony_ci#include "vkPlatform.hpp"
35e5c31af7Sopenharmony_ci#include "vkPrograms.hpp"
36e5c31af7Sopenharmony_ci#include "vkMemUtil.hpp"
37e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp"
38e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp"
39e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
40e5c31af7Sopenharmony_ci#include "vkImageUtil.hpp"
41e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
42e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp"
43e5c31af7Sopenharmony_ci#include "vkBufferWithMemory.hpp"
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci#include "deMath.h"
46e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp"
47e5c31af7Sopenharmony_ci#include "deSharedPtr.hpp"
48e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
51e5c31af7Sopenharmony_ci#include "tcuTexture.hpp"
52e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
53e5c31af7Sopenharmony_ci#include "tcuFloat.hpp"
54e5c31af7Sopenharmony_ci#include "tcuFloatFormat.hpp"
55e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
56e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci#include <string>
59e5c31af7Sopenharmony_ci#include <vector>
60e5c31af7Sopenharmony_ci#include <map>
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ciusing namespace vk;
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_cinamespace vkt
65e5c31af7Sopenharmony_ci{
66e5c31af7Sopenharmony_cinamespace image
67e5c31af7Sopenharmony_ci{
68e5c31af7Sopenharmony_cinamespace
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci// Check for three-component (non-packed) format, i.e. pixel size is a multiple of 3.
72e5c31af7Sopenharmony_cibool formatHasThreeComponents(VkFormat format)
73e5c31af7Sopenharmony_ci{
74e5c31af7Sopenharmony_ci	const tcu::TextureFormat texFormat = mapVkFormat(format);
75e5c31af7Sopenharmony_ci	return (getPixelSize(texFormat) % 3) == 0;
76e5c31af7Sopenharmony_ci}
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ciVkFormat getSingleComponentFormat(VkFormat format)
79e5c31af7Sopenharmony_ci{
80e5c31af7Sopenharmony_ci	tcu::TextureFormat texFormat = mapVkFormat(format);
81e5c31af7Sopenharmony_ci	texFormat = tcu::TextureFormat(tcu::TextureFormat::R, texFormat.type);
82e5c31af7Sopenharmony_ci	return mapTextureFormat(texFormat);
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ciinline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
86e5c31af7Sopenharmony_ci{
87e5c31af7Sopenharmony_ci	return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
88e5c31af7Sopenharmony_ci}
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_citcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
91e5c31af7Sopenharmony_ci{
92e5c31af7Sopenharmony_ci	switch (texture.type())
93e5c31af7Sopenharmony_ci	{
94e5c31af7Sopenharmony_ci		case IMAGE_TYPE_1D:
95e5c31af7Sopenharmony_ci		case IMAGE_TYPE_2D:
96e5c31af7Sopenharmony_ci		case IMAGE_TYPE_BUFFER:
97e5c31af7Sopenharmony_ci			// Not layered
98e5c31af7Sopenharmony_ci			DE_ASSERT(layer == 0);
99e5c31af7Sopenharmony_ci			return access;
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_ci		case IMAGE_TYPE_1D_ARRAY:
102e5c31af7Sopenharmony_ci			return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci		case IMAGE_TYPE_2D_ARRAY:
105e5c31af7Sopenharmony_ci		case IMAGE_TYPE_CUBE:
106e5c31af7Sopenharmony_ci		case IMAGE_TYPE_CUBE_ARRAY:
107e5c31af7Sopenharmony_ci		case IMAGE_TYPE_3D:			// 3d texture is treated as if depth was the layers
108e5c31af7Sopenharmony_ci			return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci		default:
111e5c31af7Sopenharmony_ci			DE_FATAL("Internal test error");
112e5c31af7Sopenharmony_ci			return tcu::ConstPixelBufferAccess();
113e5c31af7Sopenharmony_ci	}
114e5c31af7Sopenharmony_ci}
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_ci//! \return the size in bytes of a given level of a mipmap image, including array layers.
117e5c31af7Sopenharmony_civk::VkDeviceSize getMipmapLevelImageSizeBytes (const Texture& texture, const vk::VkFormat format, const deUint32 mipmapLevel)
118e5c31af7Sopenharmony_ci{
119e5c31af7Sopenharmony_ci	tcu::IVec3 size = texture.size(mipmapLevel);
120e5c31af7Sopenharmony_ci	return tcu::getPixelSize(vk::mapVkFormat(format)) * size.x() * size.y() * size.z();
121e5c31af7Sopenharmony_ci}
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci//! \return the size in bytes of the whole mipmap image, including all mipmap levels and array layers
124e5c31af7Sopenharmony_civk::VkDeviceSize getMipmapImageTotalSizeBytes (const Texture& texture, const vk::VkFormat format)
125e5c31af7Sopenharmony_ci{
126e5c31af7Sopenharmony_ci	vk::VkDeviceSize	size			= 0u;
127e5c31af7Sopenharmony_ci	deInt32				levelCount		= 0u;
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci	do
130e5c31af7Sopenharmony_ci	{
131e5c31af7Sopenharmony_ci		size += getMipmapLevelImageSizeBytes(texture, format, levelCount);
132e5c31af7Sopenharmony_ci		levelCount++;
133e5c31af7Sopenharmony_ci	} while (levelCount < texture.numMipmapLevels());
134e5c31af7Sopenharmony_ci	return size;
135e5c31af7Sopenharmony_ci}
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ci//! \return true if all layers match in both pixel buffers
138e5c31af7Sopenharmony_cibool comparePixelBuffers (tcu::TestLog&						log,
139e5c31af7Sopenharmony_ci						  const Texture&					texture,
140e5c31af7Sopenharmony_ci						  const VkFormat					format,
141e5c31af7Sopenharmony_ci						  const tcu::ConstPixelBufferAccess	reference,
142e5c31af7Sopenharmony_ci						  const tcu::ConstPixelBufferAccess	result,
143e5c31af7Sopenharmony_ci						  const deUint32					mipmapLevel = 0u)
144e5c31af7Sopenharmony_ci{
145e5c31af7Sopenharmony_ci	DE_ASSERT(reference.getFormat() == result.getFormat());
146e5c31af7Sopenharmony_ci	DE_ASSERT(reference.getSize() == result.getSize());
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci	const bool is3d = (texture.type() == IMAGE_TYPE_3D);
149e5c31af7Sopenharmony_ci	const int numLayersOrSlices = (is3d ? texture.size(mipmapLevel).z() : texture.numLayers());
150e5c31af7Sopenharmony_ci	const int numCubeFaces = 6;
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci	int passedLayers = 0;
153e5c31af7Sopenharmony_ci	for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
154e5c31af7Sopenharmony_ci	{
155e5c31af7Sopenharmony_ci		const std::string comparisonName = "Comparison" + de::toString(layerNdx);
156e5c31af7Sopenharmony_ci		const std::string comparisonDesc = "Image Comparison, " +
157e5c31af7Sopenharmony_ci			(isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
158e5c31af7Sopenharmony_ci			is3d			 ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx) + " , level " + de::toString(mipmapLevel));
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci		const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
161e5c31af7Sopenharmony_ci		const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci		bool ok = false;
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci		switch (tcu::getTextureChannelClass(mapVkFormat(format).type))
166e5c31af7Sopenharmony_ci		{
167e5c31af7Sopenharmony_ci			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
168e5c31af7Sopenharmony_ci			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
169e5c31af7Sopenharmony_ci			{
170e5c31af7Sopenharmony_ci				ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
171e5c31af7Sopenharmony_ci				break;
172e5c31af7Sopenharmony_ci			}
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
175e5c31af7Sopenharmony_ci			{
176e5c31af7Sopenharmony_ci				// Allow error of minimum representable difference
177e5c31af7Sopenharmony_ci				tcu::Vec4 threshold(1.0f / ((tcu::UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()) - 1u).cast<float>());
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci				// Add 1 ULP of fp32 imprecision to account for image comparison fp32 math with unorm->float conversions.
180e5c31af7Sopenharmony_ci				threshold += tcu::Vec4(std::numeric_limits<float>::epsilon());
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci				ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
183e5c31af7Sopenharmony_ci				break;
184e5c31af7Sopenharmony_ci			}
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
187e5c31af7Sopenharmony_ci			{
188e5c31af7Sopenharmony_ci				const tcu::UVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u;
189e5c31af7Sopenharmony_ci				// To avoid bit-shifting with negative value, which is undefined behaviour.
190e5c31af7Sopenharmony_ci				const tcu::UVec4 fixedBitDepth = tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u), tcu::greaterThanEqual(bitDepth.cast<deInt32>(), tcu::IVec4(0, 0, 0, 0)));
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ci				// Allow error of minimum representable difference
193e5c31af7Sopenharmony_ci				const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ci				ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
196e5c31af7Sopenharmony_ci				break;
197e5c31af7Sopenharmony_ci			}
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_ci			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
200e5c31af7Sopenharmony_ci			{
201e5c31af7Sopenharmony_ci				// Convert target format ulps to float ulps and allow 1 ulp difference
202e5c31af7Sopenharmony_ci				const tcu::UVec4 threshold (tcu::UVec4(1u) << (tcu::UVec4(23) - tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>()));
203e5c31af7Sopenharmony_ci
204e5c31af7Sopenharmony_ci				ok = tcu::floatUlpThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
205e5c31af7Sopenharmony_ci				break;
206e5c31af7Sopenharmony_ci			}
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_ci			default:
209e5c31af7Sopenharmony_ci				DE_FATAL("Unknown channel class");
210e5c31af7Sopenharmony_ci		}
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci		if (ok)
213e5c31af7Sopenharmony_ci			++passedLayers;
214e5c31af7Sopenharmony_ci	}
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ci	return passedLayers == numLayersOrSlices;
217e5c31af7Sopenharmony_ci}
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_ci//!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
220e5c31af7Sopenharmony_civoid replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
221e5c31af7Sopenharmony_ci{
222e5c31af7Sopenharmony_ci	DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_ci	for (int z = 0; z < access.getDepth(); ++z)
225e5c31af7Sopenharmony_ci	for (int y = 0; y < access.getHeight(); ++y)
226e5c31af7Sopenharmony_ci	for (int x = 0; x < access.getWidth(); ++x)
227e5c31af7Sopenharmony_ci	{
228e5c31af7Sopenharmony_ci		const tcu::Vec4 color(access.getPixel(x, y, z));
229e5c31af7Sopenharmony_ci		tcu::Vec4 newColor = color;
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; ++i)
232e5c31af7Sopenharmony_ci		{
233e5c31af7Sopenharmony_ci			if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
234e5c31af7Sopenharmony_ci			{
235e5c31af7Sopenharmony_ci				const tcu::Float16 f(color[i]);
236e5c31af7Sopenharmony_ci				if (f.isDenorm() || f.isInf() || f.isNaN())
237e5c31af7Sopenharmony_ci					newColor[i] = 0.0f;
238e5c31af7Sopenharmony_ci			}
239e5c31af7Sopenharmony_ci			else
240e5c31af7Sopenharmony_ci			{
241e5c31af7Sopenharmony_ci				const tcu::Float32 f(color[i]);
242e5c31af7Sopenharmony_ci				if (f.isDenorm() || f.isInf() || f.isNaN())
243e5c31af7Sopenharmony_ci					newColor[i] = 0.0f;
244e5c31af7Sopenharmony_ci			}
245e5c31af7Sopenharmony_ci		}
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci		if (newColor != color)
248e5c31af7Sopenharmony_ci			access.setPixel(newColor, x, y, z);
249e5c31af7Sopenharmony_ci	}
250e5c31af7Sopenharmony_ci}
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci//!< replace invalid pixels in the image (-128)
253e5c31af7Sopenharmony_civoid replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
254e5c31af7Sopenharmony_ci{
255e5c31af7Sopenharmony_ci	DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci	for (int z = 0; z < access.getDepth(); ++z)
258e5c31af7Sopenharmony_ci	for (int y = 0; y < access.getHeight(); ++y)
259e5c31af7Sopenharmony_ci	for (int x = 0; x < access.getWidth(); ++x)
260e5c31af7Sopenharmony_ci	{
261e5c31af7Sopenharmony_ci		const tcu::IVec4 color(access.getPixelInt(x, y, z));
262e5c31af7Sopenharmony_ci		tcu::IVec4 newColor = color;
263e5c31af7Sopenharmony_ci
264e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; ++i)
265e5c31af7Sopenharmony_ci		{
266e5c31af7Sopenharmony_ci			const deInt32 oldColor(color[i]);
267e5c31af7Sopenharmony_ci			if (oldColor == -128) newColor[i] = -127;
268e5c31af7Sopenharmony_ci		}
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci		if (newColor != color)
271e5c31af7Sopenharmony_ci		access.setPixel(newColor, x, y, z);
272e5c31af7Sopenharmony_ci	}
273e5c31af7Sopenharmony_ci}
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_citcu::Vec4 getMiddleValue(VkFormat imageFormat)
276e5c31af7Sopenharmony_ci{
277e5c31af7Sopenharmony_ci	tcu::TextureFormat		format	= mapVkFormat(imageFormat);
278e5c31af7Sopenharmony_ci	tcu::TextureFormatInfo	fmtInfo	= tcu::getTextureFormatInfo(format);
279e5c31af7Sopenharmony_ci	tcu::Vec4				val		= (fmtInfo.valueMax - fmtInfo.valueMin) * tcu::Vec4(0.5f);
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci	if (isIntegerFormat(imageFormat))
282e5c31af7Sopenharmony_ci		val = floor(val);
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci	return val;
285e5c31af7Sopenharmony_ci}
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_citcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat, bool constantValue = false)
288e5c31af7Sopenharmony_ci{
289e5c31af7Sopenharmony_ci	// Generate a reference image data using the storage format
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci	tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
292e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess access = reference.getAccess();
293e5c31af7Sopenharmony_ci
294e5c31af7Sopenharmony_ci	const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
295e5c31af7Sopenharmony_ci	const float storeColorBias = computeStoreColorBias(imageFormat);
296e5c31af7Sopenharmony_ci
297e5c31af7Sopenharmony_ci	const bool srgbFormat = isSrgbFormat(imageFormat);
298e5c31af7Sopenharmony_ci	const bool intFormat = isIntegerFormat(imageFormat);
299e5c31af7Sopenharmony_ci	const bool storeNegativeValues = isSignedFormat(imageFormat) && (storeColorBias == 0);
300e5c31af7Sopenharmony_ci	const int xMax = imageSize.x() - 1;
301e5c31af7Sopenharmony_ci	const int yMax = imageSize.y() - 1;
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci	for (int z = 0; z < imageSize.z(); ++z)
304e5c31af7Sopenharmony_ci	for (int y = 0; y < imageSize.y(); ++y)
305e5c31af7Sopenharmony_ci	for (int x = 0; x < imageSize.x(); ++x)
306e5c31af7Sopenharmony_ci	{
307e5c31af7Sopenharmony_ci		if (constantValue)
308e5c31af7Sopenharmony_ci		{
309e5c31af7Sopenharmony_ci			access.setPixel(getMiddleValue(imageFormat), x, y, z);
310e5c31af7Sopenharmony_ci		}
311e5c31af7Sopenharmony_ci		else
312e5c31af7Sopenharmony_ci		{
313e5c31af7Sopenharmony_ci			tcu::IVec4 color = tcu::IVec4(x ^ y ^ z, (xMax - x) ^ y ^ z, x ^ (yMax - y) ^ z, (xMax - x) ^ (yMax - y) ^ z);
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci			if (storeNegativeValues)
316e5c31af7Sopenharmony_ci				color -= tcu::IVec4(deRoundFloatToInt32((float)de::max(xMax, yMax) / 2.0f));
317e5c31af7Sopenharmony_ci
318e5c31af7Sopenharmony_ci			if (intFormat)
319e5c31af7Sopenharmony_ci				access.setPixel(color, x, y, z);
320e5c31af7Sopenharmony_ci			else
321e5c31af7Sopenharmony_ci			{
322e5c31af7Sopenharmony_ci				if (srgbFormat)
323e5c31af7Sopenharmony_ci					access.setPixel(tcu::linearToSRGB(color.asFloat() * storeColorScale + storeColorBias), x, y, z);
324e5c31af7Sopenharmony_ci				else
325e5c31af7Sopenharmony_ci					access.setPixel(color.asFloat() * storeColorScale + storeColorBias, x, y, z);
326e5c31af7Sopenharmony_ci			}
327e5c31af7Sopenharmony_ci		}
328e5c31af7Sopenharmony_ci	}
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	// If the image is to be accessed as a float texture, get rid of invalid values
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	if (isFloatFormat(readFormat) && imageFormat != readFormat)
333e5c31af7Sopenharmony_ci		replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
334e5c31af7Sopenharmony_ci	if (isSnormFormat(readFormat) && imageFormat != readFormat)
335e5c31af7Sopenharmony_ci		replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci	return reference;
338e5c31af7Sopenharmony_ci}
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ciinline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, bool constantValue = false)
341e5c31af7Sopenharmony_ci{
342e5c31af7Sopenharmony_ci	return generateReferenceImage(imageSize, imageFormat, imageFormat, constantValue);
343e5c31af7Sopenharmony_ci}
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_civoid flipHorizontally (const tcu::PixelBufferAccess access)
346e5c31af7Sopenharmony_ci{
347e5c31af7Sopenharmony_ci	const int xMax = access.getWidth() - 1;
348e5c31af7Sopenharmony_ci	const int halfWidth = access.getWidth() / 2;
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci	if (isIntegerFormat(mapTextureFormat(access.getFormat())))
351e5c31af7Sopenharmony_ci		for (int z = 0; z < access.getDepth(); z++)
352e5c31af7Sopenharmony_ci		for (int y = 0; y < access.getHeight(); y++)
353e5c31af7Sopenharmony_ci		for (int x = 0; x < halfWidth; x++)
354e5c31af7Sopenharmony_ci		{
355e5c31af7Sopenharmony_ci			const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
356e5c31af7Sopenharmony_ci			access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
357e5c31af7Sopenharmony_ci			access.setPixel(temp, x, y, z);
358e5c31af7Sopenharmony_ci		}
359e5c31af7Sopenharmony_ci	else
360e5c31af7Sopenharmony_ci		for (int z = 0; z < access.getDepth(); z++)
361e5c31af7Sopenharmony_ci		for (int y = 0; y < access.getHeight(); y++)
362e5c31af7Sopenharmony_ci		for (int x = 0; x < halfWidth; x++)
363e5c31af7Sopenharmony_ci		{
364e5c31af7Sopenharmony_ci			const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
365e5c31af7Sopenharmony_ci			access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
366e5c31af7Sopenharmony_ci			access.setPixel(temp, x, y, z);
367e5c31af7Sopenharmony_ci		}
368e5c31af7Sopenharmony_ci}
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ciinline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
371e5c31af7Sopenharmony_ci{
372e5c31af7Sopenharmony_ci	const bool isAlphaOnly = (isAlphaOnlyFormat(format0) || isAlphaOnlyFormat(format1));
373e5c31af7Sopenharmony_ci	return format0 == format1 || (mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize() && !isAlphaOnly);
374e5c31af7Sopenharmony_ci}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_civoid commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
377e5c31af7Sopenharmony_ci{
378e5c31af7Sopenharmony_ci	const DeviceInterface& vk = context.getDeviceInterface();
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
381e5c31af7Sopenharmony_ci	const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
382e5c31af7Sopenharmony_ci		VK_ACCESS_SHADER_WRITE_BIT, 0u,
383e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
384e5c31af7Sopenharmony_ci		image, fullImageSubresourceRange);
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier);
387e5c31af7Sopenharmony_ci}
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_civoid commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
390e5c31af7Sopenharmony_ci{
391e5c31af7Sopenharmony_ci	const DeviceInterface& vk = context.getDeviceInterface();
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_ci	const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
394e5c31af7Sopenharmony_ci		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
395e5c31af7Sopenharmony_ci		buffer, 0ull, bufferSizeBytes);
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
398e5c31af7Sopenharmony_ci}
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci//! Copy all layers of an image to a buffer.
401e5c31af7Sopenharmony_civoid commandCopyImageToBuffer (Context&					context,
402e5c31af7Sopenharmony_ci							   const VkCommandBuffer	cmdBuffer,
403e5c31af7Sopenharmony_ci							   const VkImage			image,
404e5c31af7Sopenharmony_ci							   const VkBuffer			buffer,
405e5c31af7Sopenharmony_ci							   const VkDeviceSize		bufferSizeBytes,
406e5c31af7Sopenharmony_ci							   const Texture&			texture)
407e5c31af7Sopenharmony_ci{
408e5c31af7Sopenharmony_ci	const DeviceInterface& vk = context.getDeviceInterface();
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
411e5c31af7Sopenharmony_ci	const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
412e5c31af7Sopenharmony_ci		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
413e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
414e5c31af7Sopenharmony_ci		image, fullImageSubresourceRange);
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ci	const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
417e5c31af7Sopenharmony_ci
418e5c31af7Sopenharmony_ci	const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
419e5c31af7Sopenharmony_ci		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
420e5c31af7Sopenharmony_ci		buffer, 0ull, bufferSizeBytes);
421e5c31af7Sopenharmony_ci
422e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier);
423e5c31af7Sopenharmony_ci	vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &copyRegion);
424e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &copyBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
425e5c31af7Sopenharmony_ci}
426e5c31af7Sopenharmony_ci
427e5c31af7Sopenharmony_ci//! Copy all layers of a mipmap image to a buffer.
428e5c31af7Sopenharmony_civoid commandCopyMipmapImageToBuffer (Context&				context,
429e5c31af7Sopenharmony_ci									 const VkCommandBuffer	cmdBuffer,
430e5c31af7Sopenharmony_ci									 const VkImage			image,
431e5c31af7Sopenharmony_ci									 const VkFormat			imageFormat,
432e5c31af7Sopenharmony_ci									 const VkBuffer			buffer,
433e5c31af7Sopenharmony_ci									 const VkDeviceSize		bufferSizeBytes,
434e5c31af7Sopenharmony_ci									 const Texture&			texture)
435e5c31af7Sopenharmony_ci{
436e5c31af7Sopenharmony_ci	const DeviceInterface& vk = context.getDeviceInterface();
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texture.numMipmapLevels(), 0u, texture.numLayers());
439e5c31af7Sopenharmony_ci	const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
440e5c31af7Sopenharmony_ci		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
441e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
442e5c31af7Sopenharmony_ci		image, fullImageSubresourceRange);
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci	std::vector<VkBufferImageCopy> copyRegions;
445e5c31af7Sopenharmony_ci	VkDeviceSize bufferOffset = 0u;
446e5c31af7Sopenharmony_ci	for (deInt32 levelNdx = 0; levelNdx < texture.numMipmapLevels(); levelNdx++)
447e5c31af7Sopenharmony_ci	{
448e5c31af7Sopenharmony_ci		const VkBufferImageCopy copyParams =
449e5c31af7Sopenharmony_ci		{
450e5c31af7Sopenharmony_ci			bufferOffset,																				//	VkDeviceSize				bufferOffset;
451e5c31af7Sopenharmony_ci			0u,																							//	deUint32					bufferRowLength;
452e5c31af7Sopenharmony_ci			0u,																							//	deUint32					bufferImageHeight;
453e5c31af7Sopenharmony_ci			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, texture.numLayers()),	//	VkImageSubresourceLayers	imageSubresource;
454e5c31af7Sopenharmony_ci			makeOffset3D(0, 0, 0),																		//	VkOffset3D					imageOffset;
455e5c31af7Sopenharmony_ci			makeExtent3D(texture.layerSize(levelNdx)),													//	VkExtent3D					imageExtent;
456e5c31af7Sopenharmony_ci		};
457e5c31af7Sopenharmony_ci		copyRegions.push_back(copyParams);
458e5c31af7Sopenharmony_ci		bufferOffset += getMipmapLevelImageSizeBytes(texture, imageFormat, levelNdx);
459e5c31af7Sopenharmony_ci	}
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci	const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
462e5c31af7Sopenharmony_ci		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
463e5c31af7Sopenharmony_ci		buffer, 0ull, bufferSizeBytes);
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier);
466e5c31af7Sopenharmony_ci	vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, (deUint32) copyRegions.size(), copyRegions.data());
467e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &copyBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
468e5c31af7Sopenharmony_ci}
469e5c31af7Sopenharmony_ci
470e5c31af7Sopenharmony_ciclass StoreTest : public TestCase
471e5c31af7Sopenharmony_ci{
472e5c31af7Sopenharmony_cipublic:
473e5c31af7Sopenharmony_ci	enum TestFlags
474e5c31af7Sopenharmony_ci	{
475e5c31af7Sopenharmony_ci		FLAG_SINGLE_LAYER_BIND				= 0x1,	//!< Run the shader multiple times, each time binding a different layer.
476e5c31af7Sopenharmony_ci		FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER	= 0x2,	//!< Declare the format of the images in the shader code
477e5c31af7Sopenharmony_ci		FLAG_MINALIGN						= 0x4,	//!< Use bufferview offset that matches the advertised minimum alignment
478e5c31af7Sopenharmony_ci		FLAG_STORE_CONSTANT_VALUE			= 0x8,	//!< Store constant value
479e5c31af7Sopenharmony_ci	};
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci							StoreTest			(tcu::TestContext&		testCtx,
482e5c31af7Sopenharmony_ci												 const std::string&		name,
483e5c31af7Sopenharmony_ci												 const Texture&			texture,
484e5c31af7Sopenharmony_ci												 const VkFormat			format,
485e5c31af7Sopenharmony_ci												 const VkImageTiling	tiling,
486e5c31af7Sopenharmony_ci												 const deUint32			flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
487e5c31af7Sopenharmony_ci
488e5c31af7Sopenharmony_ci	virtual void			checkSupport		(Context&			context) const;
489e5c31af7Sopenharmony_ci	void					initPrograms		(SourceCollections&	programCollection) const;
490e5c31af7Sopenharmony_ci	TestInstance*			createInstance		(Context&			context) const;
491e5c31af7Sopenharmony_ci
492e5c31af7Sopenharmony_ciprivate:
493e5c31af7Sopenharmony_ci	const Texture			m_texture;
494e5c31af7Sopenharmony_ci	const VkFormat			m_format;
495e5c31af7Sopenharmony_ci	const VkImageTiling		m_tiling;
496e5c31af7Sopenharmony_ci	const bool				m_declareImageFormatInShader;
497e5c31af7Sopenharmony_ci	const bool				m_singleLayerBind;
498e5c31af7Sopenharmony_ci	const bool				m_minalign;
499e5c31af7Sopenharmony_ci	const bool				m_storeConstantValue;
500e5c31af7Sopenharmony_ci};
501e5c31af7Sopenharmony_ci
502e5c31af7Sopenharmony_ciStoreTest::StoreTest (tcu::TestContext&		testCtx,
503e5c31af7Sopenharmony_ci					  const std::string&	name,
504e5c31af7Sopenharmony_ci					  const Texture&		texture,
505e5c31af7Sopenharmony_ci					  const VkFormat		format,
506e5c31af7Sopenharmony_ci					  const VkImageTiling	tiling,
507e5c31af7Sopenharmony_ci					  const deUint32		flags)
508e5c31af7Sopenharmony_ci	: TestCase						(testCtx, name)
509e5c31af7Sopenharmony_ci	, m_texture						(texture)
510e5c31af7Sopenharmony_ci	, m_format						(format)
511e5c31af7Sopenharmony_ci	, m_tiling						(tiling)
512e5c31af7Sopenharmony_ci	, m_declareImageFormatInShader	((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
513e5c31af7Sopenharmony_ci	, m_singleLayerBind				((flags & FLAG_SINGLE_LAYER_BIND) != 0)
514e5c31af7Sopenharmony_ci	, m_minalign					((flags & FLAG_MINALIGN) != 0)
515e5c31af7Sopenharmony_ci	, m_storeConstantValue			((flags & FLAG_STORE_CONSTANT_VALUE) != 0)
516e5c31af7Sopenharmony_ci{
517e5c31af7Sopenharmony_ci	if (m_singleLayerBind)
518e5c31af7Sopenharmony_ci		DE_ASSERT(m_texture.numLayers() > 1);
519e5c31af7Sopenharmony_ci}
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_civoid StoreTest::checkSupport (Context& context) const
522e5c31af7Sopenharmony_ci{
523e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
524e5c31af7Sopenharmony_ci	if (m_format == VK_FORMAT_A8_UNORM_KHR || m_format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
525e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_maintenance5");
526e5c31af7Sopenharmony_ci
527e5c31af7Sopenharmony_ci	const VkFormatProperties3 formatProperties (context.getFormatProperties(m_format));
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci	const auto& tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures : formatProperties.linearTilingFeatures;
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_ci	if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !m_declareImageFormatInShader && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
532e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage buffer");
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !m_declareImageFormatInShader && !(tilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
535e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
538e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
541e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
544e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
545e5c31af7Sopenharmony_ci#else
546e5c31af7Sopenharmony_ci	const VkFormatProperties formatProperties(getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_format));
547e5c31af7Sopenharmony_ci	const auto tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures : formatProperties.linearTilingFeatures;
548e5c31af7Sopenharmony_ci
549e5c31af7Sopenharmony_ci	if (!m_declareImageFormatInShader)
550e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
553e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
556e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
559e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
560e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
561e5c31af7Sopenharmony_ci
562e5c31af7Sopenharmony_ci	const auto& vki				= context.getInstanceInterface();
563e5c31af7Sopenharmony_ci	const auto	physicalDevice	= context.getPhysicalDevice();
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci	VkImageFormatProperties	imageFormatProperties;
566e5c31af7Sopenharmony_ci	const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_format, mapImageType(m_texture.type()), m_tiling, (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0, &imageFormatProperties);
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_ci	if (result != VK_SUCCESS)
569e5c31af7Sopenharmony_ci	{
570e5c31af7Sopenharmony_ci		if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
571e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format unsupported for tiling");
572e5c31af7Sopenharmony_ci		else
573e5c31af7Sopenharmony_ci			TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
574e5c31af7Sopenharmony_ci	}
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ci	if (imageFormatProperties.maxArrayLayers < (uint32_t)m_texture.numLayers()) {
577e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of aray layers");
578e5c31af7Sopenharmony_ci	}
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci	if (imageFormatProperties.maxMipLevels < (uint32_t)m_texture.numMipmapLevels()) {
581e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of miplevels");
582e5c31af7Sopenharmony_ci	}
583e5c31af7Sopenharmony_ci}
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_civoid StoreTest::initPrograms (SourceCollections& programCollection) const
586e5c31af7Sopenharmony_ci{
587e5c31af7Sopenharmony_ci	const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
588e5c31af7Sopenharmony_ci	const float storeColorBias = computeStoreColorBias(m_format);
589e5c31af7Sopenharmony_ci	DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
590e5c31af7Sopenharmony_ci
591e5c31af7Sopenharmony_ci	const deUint32 xMax = m_texture.size().x() - 1;
592e5c31af7Sopenharmony_ci	const deUint32 yMax = m_texture.size().y() - 1;
593e5c31af7Sopenharmony_ci	const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
594e5c31af7Sopenharmony_ci	const bool storeNegativeValues = isSignedFormat(m_format) && (storeColorBias == 0);
595e5c31af7Sopenharmony_ci	bool useClamp = false;
596e5c31af7Sopenharmony_ci	const std::string colorType = signednessPrefix + "vec4";
597e5c31af7Sopenharmony_ci	std::string colorBaseExpr = colorType + "(";
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci	std::string colorExpr;
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_ci	if (m_storeConstantValue)
602e5c31af7Sopenharmony_ci	{
603e5c31af7Sopenharmony_ci		tcu::Vec4 val = getMiddleValue(m_format);
604e5c31af7Sopenharmony_ci
605e5c31af7Sopenharmony_ci		if (isIntegerFormat(m_format))
606e5c31af7Sopenharmony_ci		{
607e5c31af7Sopenharmony_ci			colorExpr = colorBaseExpr
608e5c31af7Sopenharmony_ci						+ de::toString(static_cast<deInt64>(val.x())) + ", "
609e5c31af7Sopenharmony_ci						+ de::toString(static_cast<deInt64>(val.y())) + ", "
610e5c31af7Sopenharmony_ci						+ de::toString(static_cast<deInt64>(val.z())) + ", "
611e5c31af7Sopenharmony_ci						+ de::toString(static_cast<deInt64>(val.w())) + ")";
612e5c31af7Sopenharmony_ci		}
613e5c31af7Sopenharmony_ci		else
614e5c31af7Sopenharmony_ci		{
615e5c31af7Sopenharmony_ci			colorExpr = colorBaseExpr
616e5c31af7Sopenharmony_ci						+ de::toString(val.x()) + ", "
617e5c31af7Sopenharmony_ci						+ de::toString(val.y()) + ", "
618e5c31af7Sopenharmony_ci						+ de::toString(val.z()) + ", "
619e5c31af7Sopenharmony_ci						+ de::toString(val.w()) + ")";
620e5c31af7Sopenharmony_ci		}
621e5c31af7Sopenharmony_ci	}
622e5c31af7Sopenharmony_ci	else
623e5c31af7Sopenharmony_ci	{
624e5c31af7Sopenharmony_ci		colorBaseExpr = colorBaseExpr
625e5c31af7Sopenharmony_ci						+ "gx^gy^gz, "
626e5c31af7Sopenharmony_ci						+ "(" + de::toString(xMax) + "-gx)^gy^gz, "
627e5c31af7Sopenharmony_ci						+ "gx^(" + de::toString(yMax) + "-gy)^gz, "
628e5c31af7Sopenharmony_ci						+ "(" + de::toString(xMax) + "-gx)^(" + de::toString(yMax) + "-gy)^gz)";
629e5c31af7Sopenharmony_ci
630e5c31af7Sopenharmony_ci		// Large integer values may not be represented with formats with low bit depths
631e5c31af7Sopenharmony_ci		if (isIntegerFormat(m_format))
632e5c31af7Sopenharmony_ci		{
633e5c31af7Sopenharmony_ci			const deInt64 minStoreValue = storeNegativeValues ? 0 - deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : 0;
634e5c31af7Sopenharmony_ci			const deInt64 maxStoreValue = storeNegativeValues ? deRoundFloatToInt64((float)de::max(xMax, yMax) / 2.0f) : de::max(xMax, yMax);
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci			useClamp = !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(minStoreValue), mapVkFormat(m_format)) ||
637e5c31af7Sopenharmony_ci					   !isRepresentableIntegerValue(tcu::Vector<deInt64, 4>(maxStoreValue), mapVkFormat(m_format));
638e5c31af7Sopenharmony_ci		}
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci		// Clamp if integer value cannot be represented with the current format
641e5c31af7Sopenharmony_ci		if (useClamp)
642e5c31af7Sopenharmony_ci		{
643e5c31af7Sopenharmony_ci			const tcu::IVec4 bitDepths = tcu::getTextureFormatBitDepth(mapVkFormat(m_format));
644e5c31af7Sopenharmony_ci			tcu::IVec4 minRepresentableValue;
645e5c31af7Sopenharmony_ci			tcu::IVec4 maxRepresentableValue;
646e5c31af7Sopenharmony_ci
647e5c31af7Sopenharmony_ci			switch (tcu::getTextureChannelClass(mapVkFormat(m_format).type))
648e5c31af7Sopenharmony_ci			{
649e5c31af7Sopenharmony_ci				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
650e5c31af7Sopenharmony_ci				{
651e5c31af7Sopenharmony_ci					minRepresentableValue = tcu::IVec4(0);
652e5c31af7Sopenharmony_ci					maxRepresentableValue = (tcu::IVec4(1) << bitDepths) - tcu::IVec4(1);
653e5c31af7Sopenharmony_ci					break;
654e5c31af7Sopenharmony_ci				}
655e5c31af7Sopenharmony_ci
656e5c31af7Sopenharmony_ci				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
657e5c31af7Sopenharmony_ci				{
658e5c31af7Sopenharmony_ci					minRepresentableValue = -(tcu::IVec4(1) << bitDepths - tcu::IVec4(1));
659e5c31af7Sopenharmony_ci					maxRepresentableValue = (tcu::IVec4(1) << (bitDepths - tcu::IVec4(1))) - tcu::IVec4(1);
660e5c31af7Sopenharmony_ci					break;
661e5c31af7Sopenharmony_ci				}
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci				default:
664e5c31af7Sopenharmony_ci					DE_ASSERT(isIntegerFormat(m_format));
665e5c31af7Sopenharmony_ci			}
666e5c31af7Sopenharmony_ci
667e5c31af7Sopenharmony_ci			colorBaseExpr = "clamp(" + colorBaseExpr + ", "
668e5c31af7Sopenharmony_ci							+ signednessPrefix + "vec4" + de::toString(minRepresentableValue) + ", "
669e5c31af7Sopenharmony_ci							+ signednessPrefix + "vec4" + de::toString(maxRepresentableValue) + ")";
670e5c31af7Sopenharmony_ci		}
671e5c31af7Sopenharmony_ci
672e5c31af7Sopenharmony_ci		colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
673e5c31af7Sopenharmony_ci					+ (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
674e5c31af7Sopenharmony_ci
675e5c31af7Sopenharmony_ci		if (storeNegativeValues)
676e5c31af7Sopenharmony_ci			colorExpr += "-" + de::toString(deRoundFloatToInt32((float)deMax32(xMax, yMax) / 2.0f));
677e5c31af7Sopenharmony_ci	}
678e5c31af7Sopenharmony_ci
679e5c31af7Sopenharmony_ci	const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
680e5c31af7Sopenharmony_ci	const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci	const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
683e5c31af7Sopenharmony_ci	const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_ci	std::string maybeFmtQualStr = m_declareImageFormatInShader ? ", " + getShaderImageFormatQualifier(mapVkFormat(m_format)) : "";
686e5c31af7Sopenharmony_ci
687e5c31af7Sopenharmony_ci	std::ostringstream src;
688e5c31af7Sopenharmony_ci	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
689e5c31af7Sopenharmony_ci		<< "\n"
690e5c31af7Sopenharmony_ci		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
691e5c31af7Sopenharmony_ci		<< "layout (binding = 0" << maybeFmtQualStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
692e5c31af7Sopenharmony_ci
693e5c31af7Sopenharmony_ci	if (m_singleLayerBind)
694e5c31af7Sopenharmony_ci		src << "layout (binding = 1) readonly uniform Constants {\n"
695e5c31af7Sopenharmony_ci			<< "    int u_layerNdx;\n"
696e5c31af7Sopenharmony_ci			<< "};\n";
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci	src << "\n"
699e5c31af7Sopenharmony_ci		<< "void main (void)\n"
700e5c31af7Sopenharmony_ci		<< "{\n"
701e5c31af7Sopenharmony_ci		<< "    int gx = int(gl_GlobalInvocationID.x);\n"
702e5c31af7Sopenharmony_ci		<< "    int gy = int(gl_GlobalInvocationID.y);\n"
703e5c31af7Sopenharmony_ci		<< "    int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
704e5c31af7Sopenharmony_ci		<< "    " << colorType << " storedColor = " << colorExpr << ";\n"
705e5c31af7Sopenharmony_ci		<< "    imageStore(u_image, " << texelCoordStr << ", storedColor);\n"
706e5c31af7Sopenharmony_ci		<< "}\n";
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ci	programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
709e5c31af7Sopenharmony_ci}
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci//! Generic test iteration algorithm for image tests
712e5c31af7Sopenharmony_ciclass BaseTestInstance : public TestInstance
713e5c31af7Sopenharmony_ci{
714e5c31af7Sopenharmony_cipublic:
715e5c31af7Sopenharmony_ci									BaseTestInstance						(Context&		context,
716e5c31af7Sopenharmony_ci																			 const Texture&	texture,
717e5c31af7Sopenharmony_ci																			 const VkFormat	format,
718e5c31af7Sopenharmony_ci																			 const bool		declareImageFormatInShader,
719e5c31af7Sopenharmony_ci																			 const bool		singleLayerBind,
720e5c31af7Sopenharmony_ci																			 const bool		minalign,
721e5c31af7Sopenharmony_ci																			 const bool		bufferLoadUniform);
722e5c31af7Sopenharmony_ci
723e5c31af7Sopenharmony_ci	tcu::TestStatus					iterate									(void);
724e5c31af7Sopenharmony_ci
725e5c31af7Sopenharmony_ci	virtual							~BaseTestInstance						(void) {}
726e5c31af7Sopenharmony_ci
727e5c31af7Sopenharmony_ciprotected:
728e5c31af7Sopenharmony_ci	virtual VkDescriptorSetLayout	prepareDescriptors						(void) = 0;
729e5c31af7Sopenharmony_ci	virtual tcu::TestStatus			verifyResult							(void) = 0;
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci	virtual void					commandBeforeCompute					(const VkCommandBuffer	cmdBuffer) = 0;
732e5c31af7Sopenharmony_ci	virtual void					commandBetweenShaderInvocations			(const VkCommandBuffer	cmdBuffer) = 0;
733e5c31af7Sopenharmony_ci	virtual void					commandAfterCompute						(const VkCommandBuffer	cmdBuffer) = 0;
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci	virtual void					commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
736e5c31af7Sopenharmony_ci																			 const VkPipelineLayout pipelineLayout,
737e5c31af7Sopenharmony_ci																			 const int				layerNdx) = 0;
738e5c31af7Sopenharmony_ci	virtual deUint32				getViewOffset							(Context&		context,
739e5c31af7Sopenharmony_ci																			 const VkFormat	format,
740e5c31af7Sopenharmony_ci																			 bool			uniform);
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci	const Texture					m_texture;
743e5c31af7Sopenharmony_ci	const VkFormat					m_format;
744e5c31af7Sopenharmony_ci	const bool						m_declareImageFormatInShader;
745e5c31af7Sopenharmony_ci	const bool						m_singleLayerBind;
746e5c31af7Sopenharmony_ci	const bool						m_minalign;
747e5c31af7Sopenharmony_ci	const bool						m_bufferLoadUniform;
748e5c31af7Sopenharmony_ci	const deUint32					m_srcViewOffset;
749e5c31af7Sopenharmony_ci	const deUint32					m_dstViewOffset;
750e5c31af7Sopenharmony_ci};
751e5c31af7Sopenharmony_ci
752e5c31af7Sopenharmony_ciBaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool bufferLoadUniform)
753e5c31af7Sopenharmony_ci	: TestInstance					(context)
754e5c31af7Sopenharmony_ci	, m_texture						(texture)
755e5c31af7Sopenharmony_ci	, m_format						(format)
756e5c31af7Sopenharmony_ci	, m_declareImageFormatInShader	(declareImageFormatInShader)
757e5c31af7Sopenharmony_ci	, m_singleLayerBind				(singleLayerBind)
758e5c31af7Sopenharmony_ci	, m_minalign					(minalign)
759e5c31af7Sopenharmony_ci	, m_bufferLoadUniform			(bufferLoadUniform)
760e5c31af7Sopenharmony_ci	, m_srcViewOffset				(getViewOffset(context, format, m_bufferLoadUniform))
761e5c31af7Sopenharmony_ci	, m_dstViewOffset				(getViewOffset(context, formatHasThreeComponents(format) ? getSingleComponentFormat(format) : format, false))
762e5c31af7Sopenharmony_ci{
763e5c31af7Sopenharmony_ci}
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_citcu::TestStatus BaseTestInstance::iterate (void)
766e5c31af7Sopenharmony_ci{
767e5c31af7Sopenharmony_ci	const DeviceInterface&			vk					= m_context.getDeviceInterface();
768e5c31af7Sopenharmony_ci	const VkDevice					device				= m_context.getDevice();
769e5c31af7Sopenharmony_ci	const VkQueue					queue				= m_context.getUniversalQueue();
770e5c31af7Sopenharmony_ci	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
771e5c31af7Sopenharmony_ci
772e5c31af7Sopenharmony_ci	const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
773e5c31af7Sopenharmony_ci
774e5c31af7Sopenharmony_ci	const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
775e5c31af7Sopenharmony_ci	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
776e5c31af7Sopenharmony_ci	const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
777e5c31af7Sopenharmony_ci
778e5c31af7Sopenharmony_ci	const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
779e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci	beginCommandBuffer(vk, *cmdBuffer);
782e5c31af7Sopenharmony_ci
783e5c31af7Sopenharmony_ci	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
784e5c31af7Sopenharmony_ci	commandBeforeCompute(*cmdBuffer);
785e5c31af7Sopenharmony_ci
786e5c31af7Sopenharmony_ci	const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
787e5c31af7Sopenharmony_ci	const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
788e5c31af7Sopenharmony_ci	for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
789e5c31af7Sopenharmony_ci	{
790e5c31af7Sopenharmony_ci		commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci		if (layerNdx > 0)
793e5c31af7Sopenharmony_ci			commandBetweenShaderInvocations(*cmdBuffer);
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci		vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
796e5c31af7Sopenharmony_ci	}
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_ci	commandAfterCompute(*cmdBuffer);
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_ci	endCommandBuffer(vk, *cmdBuffer);
801e5c31af7Sopenharmony_ci
802e5c31af7Sopenharmony_ci	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
803e5c31af7Sopenharmony_ci
804e5c31af7Sopenharmony_ci	return verifyResult();
805e5c31af7Sopenharmony_ci}
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci//! Base store test implementation
808e5c31af7Sopenharmony_ciclass StoreTestInstance : public BaseTestInstance
809e5c31af7Sopenharmony_ci{
810e5c31af7Sopenharmony_cipublic:
811e5c31af7Sopenharmony_ci									StoreTestInstance						(Context&		context,
812e5c31af7Sopenharmony_ci																			 const Texture&	texture,
813e5c31af7Sopenharmony_ci																			 const VkFormat	format,
814e5c31af7Sopenharmony_ci																			 const bool		declareImageFormatInShader,
815e5c31af7Sopenharmony_ci																			 const bool		singleLayerBind,
816e5c31af7Sopenharmony_ci																			 const bool		minalign,
817e5c31af7Sopenharmony_ci																			 const bool		storeConstantValue);
818e5c31af7Sopenharmony_ci
819e5c31af7Sopenharmony_ciprotected:
820e5c31af7Sopenharmony_ci	virtual tcu::TestStatus			verifyResult							(void);
821e5c31af7Sopenharmony_ci
822e5c31af7Sopenharmony_ci	// Add empty implementations for functions that might be not needed
823e5c31af7Sopenharmony_ci	void							commandBeforeCompute					(const VkCommandBuffer) {}
824e5c31af7Sopenharmony_ci	void							commandBetweenShaderInvocations			(const VkCommandBuffer) {}
825e5c31af7Sopenharmony_ci	void							commandAfterCompute						(const VkCommandBuffer) {}
826e5c31af7Sopenharmony_ci
827e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>	m_imageBuffer;
828e5c31af7Sopenharmony_ci	const VkDeviceSize				m_imageSizeBytes;
829e5c31af7Sopenharmony_ci	bool							m_storeConstantValue;
830e5c31af7Sopenharmony_ci};
831e5c31af7Sopenharmony_ci
832e5c31af7Sopenharmony_cideUint32 BaseTestInstance::getViewOffset(Context&			context,
833e5c31af7Sopenharmony_ci										 const VkFormat		format,
834e5c31af7Sopenharmony_ci										 bool				uniform)
835e5c31af7Sopenharmony_ci{
836e5c31af7Sopenharmony_ci	if (m_minalign)
837e5c31af7Sopenharmony_ci	{
838e5c31af7Sopenharmony_ci		if (!context.getTexelBufferAlignmentFeaturesEXT().texelBufferAlignment)
839e5c31af7Sopenharmony_ci			return (deUint32)context.getDeviceProperties().limits.minTexelBufferOffsetAlignment;
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci		VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT alignmentProperties;
842e5c31af7Sopenharmony_ci		deMemset(&alignmentProperties, 0, sizeof(alignmentProperties));
843e5c31af7Sopenharmony_ci		alignmentProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT;
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_ci		VkPhysicalDeviceProperties2 properties2;
846e5c31af7Sopenharmony_ci		deMemset(&properties2, 0, sizeof(properties2));
847e5c31af7Sopenharmony_ci		properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
848e5c31af7Sopenharmony_ci		properties2.pNext = &alignmentProperties;
849e5c31af7Sopenharmony_ci
850e5c31af7Sopenharmony_ci		context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties2);
851e5c31af7Sopenharmony_ci
852e5c31af7Sopenharmony_ci		VkBool32 singleTexelAlignment = uniform ? alignmentProperties.uniformTexelBufferOffsetSingleTexelAlignment :
853e5c31af7Sopenharmony_ci												  alignmentProperties.storageTexelBufferOffsetSingleTexelAlignment;
854e5c31af7Sopenharmony_ci		VkDeviceSize align = uniform ? alignmentProperties.uniformTexelBufferOffsetAlignmentBytes :
855e5c31af7Sopenharmony_ci									   alignmentProperties.storageTexelBufferOffsetAlignmentBytes;
856e5c31af7Sopenharmony_ci
857e5c31af7Sopenharmony_ci		VkDeviceSize texelSize = formatHasThreeComponents(format) ? tcu::getChannelSize(vk::mapVkFormat(format).type) : tcu::getPixelSize(vk::mapVkFormat(format));
858e5c31af7Sopenharmony_ci
859e5c31af7Sopenharmony_ci		if (singleTexelAlignment)
860e5c31af7Sopenharmony_ci			align = de::min(align, texelSize);
861e5c31af7Sopenharmony_ci
862e5c31af7Sopenharmony_ci		return (deUint32)align;
863e5c31af7Sopenharmony_ci	}
864e5c31af7Sopenharmony_ci
865e5c31af7Sopenharmony_ci	return 0;
866e5c31af7Sopenharmony_ci}
867e5c31af7Sopenharmony_ci
868e5c31af7Sopenharmony_ciStoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind, const bool minalign, const bool storeConstantValue)
869e5c31af7Sopenharmony_ci	: BaseTestInstance		(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, false)
870e5c31af7Sopenharmony_ci	, m_imageSizeBytes		(getImageSizeBytes(texture.size(), format))
871e5c31af7Sopenharmony_ci	, m_storeConstantValue	(storeConstantValue)
872e5c31af7Sopenharmony_ci{
873e5c31af7Sopenharmony_ci	const DeviceInterface&	vk			= m_context.getDeviceInterface();
874e5c31af7Sopenharmony_ci	const VkDevice			device		= m_context.getDevice();
875e5c31af7Sopenharmony_ci	Allocator&				allocator	= m_context.getDefaultAllocator();
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci	// A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
878e5c31af7Sopenharmony_ci
879e5c31af7Sopenharmony_ci	m_imageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
880e5c31af7Sopenharmony_ci		vk, device, allocator,
881e5c31af7Sopenharmony_ci		makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
882e5c31af7Sopenharmony_ci		MemoryRequirement::HostVisible));
883e5c31af7Sopenharmony_ci}
884e5c31af7Sopenharmony_ci
885e5c31af7Sopenharmony_citcu::TestStatus StoreTestInstance::verifyResult	(void)
886e5c31af7Sopenharmony_ci{
887e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
888e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
889e5c31af7Sopenharmony_ci
890e5c31af7Sopenharmony_ci	const tcu::IVec3 imageSize = m_texture.size();
891e5c31af7Sopenharmony_ci	const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format, m_storeConstantValue);
892e5c31af7Sopenharmony_ci
893e5c31af7Sopenharmony_ci	const Allocation& alloc = m_imageBuffer->getAllocation();
894e5c31af7Sopenharmony_ci	invalidateAlloc(vk, device, alloc);
895e5c31af7Sopenharmony_ci	const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, (const char *)alloc.getHostPtr() + m_dstViewOffset);
896e5c31af7Sopenharmony_ci
897e5c31af7Sopenharmony_ci	if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
898e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Passed");
899e5c31af7Sopenharmony_ci	else
900e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Image comparison failed");
901e5c31af7Sopenharmony_ci}
902e5c31af7Sopenharmony_ci
903e5c31af7Sopenharmony_ci//! Store test for images
904e5c31af7Sopenharmony_ciclass ImageStoreTestInstance : public StoreTestInstance
905e5c31af7Sopenharmony_ci{
906e5c31af7Sopenharmony_cipublic:
907e5c31af7Sopenharmony_ci										ImageStoreTestInstance					(Context&				context,
908e5c31af7Sopenharmony_ci																				 const Texture&			texture,
909e5c31af7Sopenharmony_ci																				 const VkFormat			format,
910e5c31af7Sopenharmony_ci																				 const VkImageTiling	tiling,
911e5c31af7Sopenharmony_ci																				 const bool				declareImageFormatInShader,
912e5c31af7Sopenharmony_ci																				 const bool				singleLayerBind,
913e5c31af7Sopenharmony_ci																				 const bool				minalign,
914e5c31af7Sopenharmony_ci																				 const bool				storeConstantValue);
915e5c31af7Sopenharmony_ci
916e5c31af7Sopenharmony_ciprotected:
917e5c31af7Sopenharmony_ci	VkDescriptorSetLayout				prepareDescriptors						(void);
918e5c31af7Sopenharmony_ci	void								commandBeforeCompute					(const VkCommandBuffer	cmdBuffer);
919e5c31af7Sopenharmony_ci	void								commandBetweenShaderInvocations			(const VkCommandBuffer	cmdBuffer);
920e5c31af7Sopenharmony_ci	void								commandAfterCompute						(const VkCommandBuffer	cmdBuffer);
921e5c31af7Sopenharmony_ci
922e5c31af7Sopenharmony_ci	void								commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
923e5c31af7Sopenharmony_ci																				 const VkPipelineLayout pipelineLayout,
924e5c31af7Sopenharmony_ci																				 const int				layerNdx);
925e5c31af7Sopenharmony_ci
926e5c31af7Sopenharmony_ci	de::MovePtr<Image>					m_image;
927e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>		m_constantsBuffer;
928e5c31af7Sopenharmony_ci	const VkDeviceSize					m_constantsBufferChunkSizeBytes;
929e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
930e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>				m_descriptorPool;
931e5c31af7Sopenharmony_ci	std::vector<SharedVkDescriptorSet>	m_allDescriptorSets;
932e5c31af7Sopenharmony_ci	std::vector<SharedVkImageView>		m_allImageViews;
933e5c31af7Sopenharmony_ci};
934e5c31af7Sopenharmony_ci
935e5c31af7Sopenharmony_ciImageStoreTestInstance::ImageStoreTestInstance (Context&			context,
936e5c31af7Sopenharmony_ci												const Texture&		texture,
937e5c31af7Sopenharmony_ci												const VkFormat		format,
938e5c31af7Sopenharmony_ci												const VkImageTiling	tiling,
939e5c31af7Sopenharmony_ci												const bool			declareImageFormatInShader,
940e5c31af7Sopenharmony_ci												const bool			singleLayerBind,
941e5c31af7Sopenharmony_ci												const bool			minalign,
942e5c31af7Sopenharmony_ci												const bool			storeConstantValue)
943e5c31af7Sopenharmony_ci	: StoreTestInstance					(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, storeConstantValue)
944e5c31af7Sopenharmony_ci	, m_constantsBufferChunkSizeBytes	(getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
945e5c31af7Sopenharmony_ci	, m_allDescriptorSets				(texture.numLayers())
946e5c31af7Sopenharmony_ci	, m_allImageViews					(texture.numLayers())
947e5c31af7Sopenharmony_ci{
948e5c31af7Sopenharmony_ci	const DeviceInterface&	vk			= m_context.getDeviceInterface();
949e5c31af7Sopenharmony_ci	const VkDevice			device		= m_context.getDevice();
950e5c31af7Sopenharmony_ci	Allocator&				allocator	= m_context.getDefaultAllocator();
951e5c31af7Sopenharmony_ci
952e5c31af7Sopenharmony_ci	m_image = de::MovePtr<Image>(new Image(
953e5c31af7Sopenharmony_ci		vk, device, allocator,
954e5c31af7Sopenharmony_ci		makeImageCreateInfo(m_texture, m_format, (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0u, tiling),
955e5c31af7Sopenharmony_ci		MemoryRequirement::Any));
956e5c31af7Sopenharmony_ci
957e5c31af7Sopenharmony_ci	// This buffer will be used to pass constants to the shader
958e5c31af7Sopenharmony_ci
959e5c31af7Sopenharmony_ci	const int numLayers = m_texture.numLayers();
960e5c31af7Sopenharmony_ci	const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
961e5c31af7Sopenharmony_ci	m_constantsBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
962e5c31af7Sopenharmony_ci		vk, device, allocator,
963e5c31af7Sopenharmony_ci		makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
964e5c31af7Sopenharmony_ci		MemoryRequirement::HostVisible));
965e5c31af7Sopenharmony_ci
966e5c31af7Sopenharmony_ci	{
967e5c31af7Sopenharmony_ci		const Allocation& alloc = m_constantsBuffer->getAllocation();
968e5c31af7Sopenharmony_ci		deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
969e5c31af7Sopenharmony_ci
970e5c31af7Sopenharmony_ci		deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
971e5c31af7Sopenharmony_ci
972e5c31af7Sopenharmony_ci		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
973e5c31af7Sopenharmony_ci		{
974e5c31af7Sopenharmony_ci			deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
975e5c31af7Sopenharmony_ci			*valuePtr = static_cast<deUint32>(layerNdx);
976e5c31af7Sopenharmony_ci		}
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ci		flushAlloc(vk, device, alloc);
979e5c31af7Sopenharmony_ci	}
980e5c31af7Sopenharmony_ci}
981e5c31af7Sopenharmony_ci
982e5c31af7Sopenharmony_ciVkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
983e5c31af7Sopenharmony_ci{
984e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
985e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
986e5c31af7Sopenharmony_ci
987e5c31af7Sopenharmony_ci	const int numLayers = m_texture.numLayers();
988e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
989e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
990e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
991e5c31af7Sopenharmony_ci		.build(vk, device);
992e5c31af7Sopenharmony_ci
993e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
994e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
995e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
996e5c31af7Sopenharmony_ci		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
997e5c31af7Sopenharmony_ci
998e5c31af7Sopenharmony_ci	if (m_singleLayerBind)
999e5c31af7Sopenharmony_ci	{
1000e5c31af7Sopenharmony_ci		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1001e5c31af7Sopenharmony_ci		{
1002e5c31af7Sopenharmony_ci			m_allDescriptorSets[layerNdx]	= makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1003e5c31af7Sopenharmony_ci			m_allImageViews[layerNdx]		= makeVkSharedPtr(makeImageView(
1004e5c31af7Sopenharmony_ci												vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
1005e5c31af7Sopenharmony_ci												makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
1006e5c31af7Sopenharmony_ci		}
1007e5c31af7Sopenharmony_ci	}
1008e5c31af7Sopenharmony_ci	else // bind all layers at once
1009e5c31af7Sopenharmony_ci	{
1010e5c31af7Sopenharmony_ci		m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1011e5c31af7Sopenharmony_ci		m_allImageViews[0] = makeVkSharedPtr(makeImageView(
1012e5c31af7Sopenharmony_ci								vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
1013e5c31af7Sopenharmony_ci								makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1014e5c31af7Sopenharmony_ci	}
1015e5c31af7Sopenharmony_ci
1016e5c31af7Sopenharmony_ci	return *m_descriptorSetLayout;  // not passing the ownership
1017e5c31af7Sopenharmony_ci}
1018e5c31af7Sopenharmony_ci
1019e5c31af7Sopenharmony_civoid ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1020e5c31af7Sopenharmony_ci{
1021e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1022e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci	const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1025e5c31af7Sopenharmony_ci	const VkImageView imageView = **m_allImageViews[layerNdx];
1026e5c31af7Sopenharmony_ci
1027e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
1028e5c31af7Sopenharmony_ci
1029e5c31af7Sopenharmony_ci	// Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
1030e5c31af7Sopenharmony_ci	const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
1031e5c31af7Sopenharmony_ci		m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
1032e5c31af7Sopenharmony_ci
1033e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
1034e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1035e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
1036e5c31af7Sopenharmony_ci		.update(vk, device);
1037e5c31af7Sopenharmony_ci	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1038e5c31af7Sopenharmony_ci}
1039e5c31af7Sopenharmony_ci
1040e5c31af7Sopenharmony_civoid ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1041e5c31af7Sopenharmony_ci{
1042e5c31af7Sopenharmony_ci	const DeviceInterface& vk = m_context.getDeviceInterface();
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1045e5c31af7Sopenharmony_ci	const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
1046e5c31af7Sopenharmony_ci		0u, VK_ACCESS_SHADER_WRITE_BIT,
1047e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1048e5c31af7Sopenharmony_ci		m_image->get(), fullImageSubresourceRange);
1049e5c31af7Sopenharmony_ci
1050e5c31af7Sopenharmony_ci	const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
1051e5c31af7Sopenharmony_ci	const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
1052e5c31af7Sopenharmony_ci		VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1053e5c31af7Sopenharmony_ci		m_constantsBuffer->get(), 0ull, constantsBufferSize);
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_ci	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
1056e5c31af7Sopenharmony_ci}
1057e5c31af7Sopenharmony_ci
1058e5c31af7Sopenharmony_civoid ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1059e5c31af7Sopenharmony_ci{
1060e5c31af7Sopenharmony_ci	commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
1061e5c31af7Sopenharmony_ci}
1062e5c31af7Sopenharmony_ci
1063e5c31af7Sopenharmony_civoid ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1064e5c31af7Sopenharmony_ci{
1065e5c31af7Sopenharmony_ci	commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1066e5c31af7Sopenharmony_ci}
1067e5c31af7Sopenharmony_ci
1068e5c31af7Sopenharmony_ci//! Store test for buffers
1069e5c31af7Sopenharmony_ciclass BufferStoreTestInstance : public StoreTestInstance
1070e5c31af7Sopenharmony_ci{
1071e5c31af7Sopenharmony_cipublic:
1072e5c31af7Sopenharmony_ci									BufferStoreTestInstance					(Context&				context,
1073e5c31af7Sopenharmony_ci																			 const Texture&			texture,
1074e5c31af7Sopenharmony_ci																			 const VkFormat			format,
1075e5c31af7Sopenharmony_ci																			 const bool				declareImageFormatInShader,
1076e5c31af7Sopenharmony_ci																			 const bool				minalign,
1077e5c31af7Sopenharmony_ci																			 const bool				storeConstantValue);
1078e5c31af7Sopenharmony_ci
1079e5c31af7Sopenharmony_ciprotected:
1080e5c31af7Sopenharmony_ci	VkDescriptorSetLayout			prepareDescriptors						(void);
1081e5c31af7Sopenharmony_ci	void							commandAfterCompute						(const VkCommandBuffer	cmdBuffer);
1082e5c31af7Sopenharmony_ci
1083e5c31af7Sopenharmony_ci	void							commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
1084e5c31af7Sopenharmony_ci																			 const VkPipelineLayout pipelineLayout,
1085e5c31af7Sopenharmony_ci																			 const int				layerNdx);
1086e5c31af7Sopenharmony_ci
1087e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
1088e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>			m_descriptorPool;
1089e5c31af7Sopenharmony_ci	Move<VkDescriptorSet>			m_descriptorSet;
1090e5c31af7Sopenharmony_ci	Move<VkBufferView>				m_bufferView;
1091e5c31af7Sopenharmony_ci};
1092e5c31af7Sopenharmony_ci
1093e5c31af7Sopenharmony_ciBufferStoreTestInstance::BufferStoreTestInstance (Context&			context,
1094e5c31af7Sopenharmony_ci												  const Texture&	texture,
1095e5c31af7Sopenharmony_ci												  const VkFormat	format,
1096e5c31af7Sopenharmony_ci												  const bool		declareImageFormatInShader,
1097e5c31af7Sopenharmony_ci												  const bool		minalign,
1098e5c31af7Sopenharmony_ci												  const bool		storeConstantValue)
1099e5c31af7Sopenharmony_ci	: StoreTestInstance(context, texture, format, declareImageFormatInShader, false, minalign, storeConstantValue)
1100e5c31af7Sopenharmony_ci{
1101e5c31af7Sopenharmony_ci}
1102e5c31af7Sopenharmony_ci
1103e5c31af7Sopenharmony_ciVkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
1104e5c31af7Sopenharmony_ci{
1105e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1106e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1107e5c31af7Sopenharmony_ci
1108e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1109e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1110e5c31af7Sopenharmony_ci		.build(vk, device);
1111e5c31af7Sopenharmony_ci
1112e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
1113e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
1114e5c31af7Sopenharmony_ci		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1115e5c31af7Sopenharmony_ci
1116e5c31af7Sopenharmony_ci	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
1117e5c31af7Sopenharmony_ci	m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_dstViewOffset, m_imageSizeBytes);
1118e5c31af7Sopenharmony_ci
1119e5c31af7Sopenharmony_ci	return *m_descriptorSetLayout;  // not passing the ownership
1120e5c31af7Sopenharmony_ci}
1121e5c31af7Sopenharmony_ci
1122e5c31af7Sopenharmony_civoid BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1123e5c31af7Sopenharmony_ci{
1124e5c31af7Sopenharmony_ci	DE_ASSERT(layerNdx == 0);
1125e5c31af7Sopenharmony_ci	DE_UNREF(layerNdx);
1126e5c31af7Sopenharmony_ci
1127e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1128e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1129e5c31af7Sopenharmony_ci
1130e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
1131e5c31af7Sopenharmony_ci		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
1132e5c31af7Sopenharmony_ci		.update(vk, device);
1133e5c31af7Sopenharmony_ci	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
1134e5c31af7Sopenharmony_ci}
1135e5c31af7Sopenharmony_ci
1136e5c31af7Sopenharmony_civoid BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1137e5c31af7Sopenharmony_ci{
1138e5c31af7Sopenharmony_ci	commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes + m_dstViewOffset);
1139e5c31af7Sopenharmony_ci}
1140e5c31af7Sopenharmony_ci
1141e5c31af7Sopenharmony_ciclass LoadStoreTest : public TestCase
1142e5c31af7Sopenharmony_ci{
1143e5c31af7Sopenharmony_cipublic:
1144e5c31af7Sopenharmony_ci	enum TestFlags
1145e5c31af7Sopenharmony_ci	{
1146e5c31af7Sopenharmony_ci		FLAG_SINGLE_LAYER_BIND					= (1 << 0),	//!< Run the shader multiple times, each time binding a different layer.
1147e5c31af7Sopenharmony_ci		FLAG_RESTRICT_IMAGES					= (1 << 1),	//!< If given, images in the shader will be qualified with "restrict".
1148e5c31af7Sopenharmony_ci		FLAG_DECLARE_FORMAT_IN_SHADER_READS		= (1 << 2),	//!< Declare the format of images being read in the shader code
1149e5c31af7Sopenharmony_ci		FLAG_DECLARE_FORMAT_IN_SHADER_WRITES	= (1 << 3),	//!< Declare the format of images being read in the shader code
1150e5c31af7Sopenharmony_ci		FLAG_MINALIGN							= (1 << 4),	//!< Use bufferview offset that matches the advertised minimum alignment
1151e5c31af7Sopenharmony_ci		FLAG_UNIFORM_TEXEL_BUFFER				= (1 << 5),	//!< Load from a uniform texel buffer rather than a storage texel buffer
1152e5c31af7Sopenharmony_ci	};
1153e5c31af7Sopenharmony_ci
1154e5c31af7Sopenharmony_ci							LoadStoreTest			(tcu::TestContext&		testCtx,
1155e5c31af7Sopenharmony_ci													 const std::string&		name,
1156e5c31af7Sopenharmony_ci													 const Texture&			texture,
1157e5c31af7Sopenharmony_ci													 const VkFormat			format,
1158e5c31af7Sopenharmony_ci													 const VkFormat			imageFormat,
1159e5c31af7Sopenharmony_ci													 const VkImageTiling	tiling,
1160e5c31af7Sopenharmony_ci													 const deUint32			flags = (FLAG_DECLARE_FORMAT_IN_SHADER_READS | FLAG_DECLARE_FORMAT_IN_SHADER_WRITES),
1161e5c31af7Sopenharmony_ci													 const deBool			imageLoadStoreLodAMD = DE_FALSE);
1162e5c31af7Sopenharmony_ci
1163e5c31af7Sopenharmony_ci	virtual void			checkSupport			(Context&				context) const;
1164e5c31af7Sopenharmony_ci	void					initPrograms			(SourceCollections&		programCollection) const;
1165e5c31af7Sopenharmony_ci	TestInstance*			createInstance			(Context&				context) const;
1166e5c31af7Sopenharmony_ci
1167e5c31af7Sopenharmony_ciprivate:
1168e5c31af7Sopenharmony_ci	const Texture			m_texture;
1169e5c31af7Sopenharmony_ci	const VkFormat			m_format;						//!< Format as accessed in the shader
1170e5c31af7Sopenharmony_ci	const VkFormat			m_imageFormat;					//!< Storage format
1171e5c31af7Sopenharmony_ci	const VkImageTiling		m_tiling;						//!< Image Tiling
1172e5c31af7Sopenharmony_ci	const bool				m_declareFormatInShaderReads;	//!< Whether the shader will specify the format layout qualifier of images being read from.
1173e5c31af7Sopenharmony_ci	const bool				m_declareFormatInShaderWrites;	//!< Whether the shader will specify the format layout qualifier of images being written to.
1174e5c31af7Sopenharmony_ci	const bool				m_singleLayerBind;
1175e5c31af7Sopenharmony_ci	const bool				m_restrictImages;
1176e5c31af7Sopenharmony_ci	const bool				m_minalign;
1177e5c31af7Sopenharmony_ci	bool					m_bufferLoadUniform;
1178e5c31af7Sopenharmony_ci	const deBool			m_imageLoadStoreLodAMD;
1179e5c31af7Sopenharmony_ci};
1180e5c31af7Sopenharmony_ci
1181e5c31af7Sopenharmony_ciLoadStoreTest::LoadStoreTest (tcu::TestContext&		testCtx,
1182e5c31af7Sopenharmony_ci							  const std::string&	name,
1183e5c31af7Sopenharmony_ci							  const Texture&		texture,
1184e5c31af7Sopenharmony_ci							  const VkFormat		format,
1185e5c31af7Sopenharmony_ci							  const VkFormat		imageFormat,
1186e5c31af7Sopenharmony_ci							  const VkImageTiling   tiling,
1187e5c31af7Sopenharmony_ci							  const deUint32		flags,
1188e5c31af7Sopenharmony_ci							  const deBool			imageLoadStoreLodAMD)
1189e5c31af7Sopenharmony_ci	: TestCase						(testCtx, name)
1190e5c31af7Sopenharmony_ci	, m_texture						(texture)
1191e5c31af7Sopenharmony_ci	, m_format						(format)
1192e5c31af7Sopenharmony_ci	, m_imageFormat					(imageFormat)
1193e5c31af7Sopenharmony_ci	, m_tiling						(tiling)
1194e5c31af7Sopenharmony_ci	, m_declareFormatInShaderReads	((flags & FLAG_DECLARE_FORMAT_IN_SHADER_READS) != 0)
1195e5c31af7Sopenharmony_ci	, m_declareFormatInShaderWrites	((flags & FLAG_DECLARE_FORMAT_IN_SHADER_WRITES) != 0)
1196e5c31af7Sopenharmony_ci	, m_singleLayerBind				((flags & FLAG_SINGLE_LAYER_BIND) != 0)
1197e5c31af7Sopenharmony_ci	, m_restrictImages				((flags & FLAG_RESTRICT_IMAGES) != 0)
1198e5c31af7Sopenharmony_ci	, m_minalign					((flags & FLAG_MINALIGN) != 0)
1199e5c31af7Sopenharmony_ci	, m_bufferLoadUniform			((flags & FLAG_UNIFORM_TEXEL_BUFFER) != 0)
1200e5c31af7Sopenharmony_ci	, m_imageLoadStoreLodAMD		(imageLoadStoreLodAMD)
1201e5c31af7Sopenharmony_ci{
1202e5c31af7Sopenharmony_ci	if (m_singleLayerBind)
1203e5c31af7Sopenharmony_ci		DE_ASSERT(m_texture.numLayers() > 1);
1204e5c31af7Sopenharmony_ci
1205e5c31af7Sopenharmony_ci	DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
1206e5c31af7Sopenharmony_ci}
1207e5c31af7Sopenharmony_ci
1208e5c31af7Sopenharmony_civoid LoadStoreTest::checkSupport (Context& context) const
1209e5c31af7Sopenharmony_ci{
1210e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
1211e5c31af7Sopenharmony_ci	if (m_format == VK_FORMAT_A8_UNORM_KHR || m_format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
1212e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_maintenance5");
1213e5c31af7Sopenharmony_ci
1214e5c31af7Sopenharmony_ci	const VkFormatProperties3 formatProperties (context.getFormatProperties(m_format));
1215e5c31af7Sopenharmony_ci	const VkFormatProperties3 imageFormatProperties (context.getFormatProperties(m_imageFormat));
1216e5c31af7Sopenharmony_ci
1217e5c31af7Sopenharmony_ci	const auto& tilingFeatures		= (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures : formatProperties.linearTilingFeatures;
1218e5c31af7Sopenharmony_ci	const auto& imageTilingFeatures	= (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? imageFormatProperties.optimalTilingFeatures : imageFormatProperties.linearTilingFeatures;
1219e5c31af7Sopenharmony_ci
1220e5c31af7Sopenharmony_ci	if (m_imageLoadStoreLodAMD)
1221e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1222e5c31af7Sopenharmony_ci
1223e5c31af7Sopenharmony_ci	if (!m_bufferLoadUniform && !m_declareFormatInShaderReads && !(tilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT))
1224e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via storage images");
1225e5c31af7Sopenharmony_ci
1226e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER && !m_declareFormatInShaderReads && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT))
1227e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via buffers");
1228e5c31af7Sopenharmony_ci
1229e5c31af7Sopenharmony_ci	if (!m_declareFormatInShaderWrites && !(tilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT))
1230e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
1231e5c31af7Sopenharmony_ci
1232e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER && !m_declareFormatInShaderWrites && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT))
1233e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via buffers");
1234e5c31af7Sopenharmony_ci
1235e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1236e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1237e5c31af7Sopenharmony_ci
1238e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1239e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
1240e5c31af7Sopenharmony_ci
1241e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1242e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
1243e5c31af7Sopenharmony_ci
1244e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1245e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1246e5c31af7Sopenharmony_ci
1247e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures))
1248e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1249e5c31af7Sopenharmony_ci
1250e5c31af7Sopenharmony_ci	if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1251e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1252e5c31af7Sopenharmony_ci
1253e5c31af7Sopenharmony_ci	if (formatHasThreeComponents(m_format))
1254e5c31af7Sopenharmony_ci	{
1255e5c31af7Sopenharmony_ci		// When the source buffer is three-component, the destination buffer is single-component.
1256e5c31af7Sopenharmony_ci		VkFormat dstFormat = getSingleComponentFormat(m_format);
1257e5c31af7Sopenharmony_ci		const VkFormatProperties3 dstFormatProperties (context.getFormatProperties(dstFormat));
1258e5c31af7Sopenharmony_ci
1259e5c31af7Sopenharmony_ci		if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1260e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1261e5c31af7Sopenharmony_ci	}
1262e5c31af7Sopenharmony_ci	else
1263e5c31af7Sopenharmony_ci		if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1264e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1265e5c31af7Sopenharmony_ci
1266e5c31af7Sopenharmony_ci	if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1267e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1268e5c31af7Sopenharmony_ci#else
1269e5c31af7Sopenharmony_ci	const vk::VkFormatProperties	formatProperties		(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1270e5c31af7Sopenharmony_ci																								   context.getPhysicalDevice(),
1271e5c31af7Sopenharmony_ci																								   m_format));
1272e5c31af7Sopenharmony_ci	const vk::VkFormatProperties	imageFormatProperties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1273e5c31af7Sopenharmony_ci																								   context.getPhysicalDevice(),
1274e5c31af7Sopenharmony_ci																								   m_imageFormat));
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_ci	const auto tilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? formatProperties.optimalTilingFeatures : formatProperties.linearTilingFeatures;
1277e5c31af7Sopenharmony_ci	const auto imageTilingFeatures = (m_tiling == vk::VK_IMAGE_TILING_OPTIMAL) ? imageFormatProperties.optimalTilingFeatures : imageFormatProperties.linearTilingFeatures;
1278e5c31af7Sopenharmony_ci
1279e5c31af7Sopenharmony_ci	if (m_imageLoadStoreLodAMD)
1280e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
1281e5c31af7Sopenharmony_ci
1282e5c31af7Sopenharmony_ci	if (!m_bufferLoadUniform && !m_declareFormatInShaderReads)
1283e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT);
1284e5c31af7Sopenharmony_ci
1285e5c31af7Sopenharmony_ci	if (!m_declareFormatInShaderWrites)
1286e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
1287e5c31af7Sopenharmony_ci
1288e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
1289e5c31af7Sopenharmony_ci		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
1290e5c31af7Sopenharmony_ci
1291e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(tilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1292e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
1293e5c31af7Sopenharmony_ci
1294e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
1295e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
1296e5c31af7Sopenharmony_ci
1297e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1298e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1299e5c31af7Sopenharmony_ci
1300e5c31af7Sopenharmony_ci	if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(imageTilingFeatures))
1301e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Underlying format not supported at all for images");
1302e5c31af7Sopenharmony_ci
1303e5c31af7Sopenharmony_ci	if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
1304e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
1305e5c31af7Sopenharmony_ci
1306e5c31af7Sopenharmony_ci	if (formatHasThreeComponents(m_format))
1307e5c31af7Sopenharmony_ci	{
1308e5c31af7Sopenharmony_ci		// When the source buffer is three-component, the destination buffer is single-component.
1309e5c31af7Sopenharmony_ci		VkFormat dstFormat = getSingleComponentFormat(m_format);
1310e5c31af7Sopenharmony_ci		const vk::VkFormatProperties	dstFormatProperties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
1311e5c31af7Sopenharmony_ci																								   context.getPhysicalDevice(),
1312e5c31af7Sopenharmony_ci																								   dstFormat));
1313e5c31af7Sopenharmony_ci
1314e5c31af7Sopenharmony_ci		if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1315e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1316e5c31af7Sopenharmony_ci	}
1317e5c31af7Sopenharmony_ci	else
1318e5c31af7Sopenharmony_ci		if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
1319e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
1320e5c31af7Sopenharmony_ci
1321e5c31af7Sopenharmony_ci	if (m_bufferLoadUniform && m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))
1322e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for uniform texel buffers");
1323e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
1324e5c31af7Sopenharmony_ci
1325e5c31af7Sopenharmony_ci	const auto& vki				= context.getInstanceInterface();
1326e5c31af7Sopenharmony_ci	const auto	physicalDevice	= context.getPhysicalDevice();
1327e5c31af7Sopenharmony_ci
1328e5c31af7Sopenharmony_ci	VkImageFormatProperties	vkImageFormatProperties;
1329e5c31af7Sopenharmony_ci	const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_imageFormat, mapImageType(m_texture.type()), m_tiling, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0, &vkImageFormatProperties);
1330e5c31af7Sopenharmony_ci
1331e5c31af7Sopenharmony_ci	if (result != VK_SUCCESS)
1332e5c31af7Sopenharmony_ci	{
1333e5c31af7Sopenharmony_ci		if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
1334e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Format unsupported for tiling");
1335e5c31af7Sopenharmony_ci		else
1336e5c31af7Sopenharmony_ci			TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
1337e5c31af7Sopenharmony_ci	}
1338e5c31af7Sopenharmony_ci
1339e5c31af7Sopenharmony_ci	if (vkImageFormatProperties.maxArrayLayers < (uint32_t)m_texture.numLayers()) {
1340e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of aray layers");
1341e5c31af7Sopenharmony_ci	}
1342e5c31af7Sopenharmony_ci
1343e5c31af7Sopenharmony_ci	if (vkImageFormatProperties.maxMipLevels < (uint32_t)m_texture.numMipmapLevels()) {
1344e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "This format and tiling combination does not support this number of miplevels");
1345e5c31af7Sopenharmony_ci	}
1346e5c31af7Sopenharmony_ci}
1347e5c31af7Sopenharmony_ci
1348e5c31af7Sopenharmony_civoid LoadStoreTest::initPrograms (SourceCollections& programCollection) const
1349e5c31af7Sopenharmony_ci{
1350e5c31af7Sopenharmony_ci	const tcu::TextureFormat	texFormat			= mapVkFormat(m_format);
1351e5c31af7Sopenharmony_ci	const int					dimension			= (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
1352e5c31af7Sopenharmony_ci	const ImageType				usedImageType		= (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
1353e5c31af7Sopenharmony_ci	const bool					noFormats			= (!m_declareFormatInShaderReads && !m_declareFormatInShaderWrites);
1354e5c31af7Sopenharmony_ci	const std::string			formatQualifierStr	= (noFormats ? "" : getShaderImageFormatQualifier(texFormat));
1355e5c31af7Sopenharmony_ci	const std::string			uniformTypeStr		= getFormatPrefix(texFormat) + "textureBuffer";
1356e5c31af7Sopenharmony_ci	const std::string			imageTypeStr		= getShaderImageType(texFormat, usedImageType);
1357e5c31af7Sopenharmony_ci	const std::string			maybeRestrictStr	= (m_restrictImages ? "restrict " : "");
1358e5c31af7Sopenharmony_ci	const std::string			xMax				= de::toString(m_texture.size().x() - 1);
1359e5c31af7Sopenharmony_ci
1360e5c31af7Sopenharmony_ci	std::ostringstream src;
1361e5c31af7Sopenharmony_ci	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1362e5c31af7Sopenharmony_ci		<< "\n";
1363e5c31af7Sopenharmony_ci
1364e5c31af7Sopenharmony_ci	if (!m_declareFormatInShaderReads || !m_declareFormatInShaderWrites)
1365e5c31af7Sopenharmony_ci	{
1366e5c31af7Sopenharmony_ci		src << "#extension GL_EXT_shader_image_load_formatted : require\n";
1367e5c31af7Sopenharmony_ci	}
1368e5c31af7Sopenharmony_ci
1369e5c31af7Sopenharmony_ci	if (m_imageLoadStoreLodAMD)
1370e5c31af7Sopenharmony_ci	{
1371e5c31af7Sopenharmony_ci		src << "#extension GL_AMD_shader_image_load_store_lod : require\n";
1372e5c31af7Sopenharmony_ci	}
1373e5c31af7Sopenharmony_ci
1374e5c31af7Sopenharmony_ci	const std::string maybeFmtQualStrReads	= m_declareFormatInShaderReads ?	", " + formatQualifierStr : "";
1375e5c31af7Sopenharmony_ci	const std::string maybeFmtQualStrWrites	= m_declareFormatInShaderWrites ?	", " + formatQualifierStr : "";
1376e5c31af7Sopenharmony_ci
1377e5c31af7Sopenharmony_ci	src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
1378e5c31af7Sopenharmony_ci
1379e5c31af7Sopenharmony_ci	if (m_bufferLoadUniform)
1380e5c31af7Sopenharmony_ci		src << "layout (binding = 0) uniform " << uniformTypeStr << " u_image0;\n";
1381e5c31af7Sopenharmony_ci	else
1382e5c31af7Sopenharmony_ci		src << "layout (binding = 0" << maybeFmtQualStrReads << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
1383e5c31af7Sopenharmony_ci
1384e5c31af7Sopenharmony_ci	// For three-component formats, the dst buffer is single-component and the shader expands the store into 3 component-wise stores.
1385e5c31af7Sopenharmony_ci	// We always use the format qualifier for the dst buffer, except when splitting it up.
1386e5c31af7Sopenharmony_ci	if (formatHasThreeComponents(m_format))
1387e5c31af7Sopenharmony_ci		src << "layout (binding = 1) " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1388e5c31af7Sopenharmony_ci	else
1389e5c31af7Sopenharmony_ci		src << "layout (binding = 1" << maybeFmtQualStrWrites << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n";
1390e5c31af7Sopenharmony_ci
1391e5c31af7Sopenharmony_ci	src << "\n"
1392e5c31af7Sopenharmony_ci		<< "void main (void)\n"
1393e5c31af7Sopenharmony_ci		<< "{\n";
1394e5c31af7Sopenharmony_ci
1395e5c31af7Sopenharmony_ci	switch (dimension)
1396e5c31af7Sopenharmony_ci	{
1397e5c31af7Sopenharmony_ci	default: DE_ASSERT(0); // fallthrough
1398e5c31af7Sopenharmony_ci	case 1:
1399e5c31af7Sopenharmony_ci		if (m_bufferLoadUniform)
1400e5c31af7Sopenharmony_ci		{
1401e5c31af7Sopenharmony_ci			// Expand the store into 3 component-wise stores.
1402e5c31af7Sopenharmony_ci			std::string type = getFormatPrefix(texFormat) + "vec4";
1403e5c31af7Sopenharmony_ci			src << "    int pos = int(gl_GlobalInvocationID.x);\n"
1404e5c31af7Sopenharmony_ci				   "    " << type << " t = texelFetch(u_image0, " + xMax + "-pos);\n";
1405e5c31af7Sopenharmony_ci			if (formatHasThreeComponents(m_format))
1406e5c31af7Sopenharmony_ci			{
1407e5c31af7Sopenharmony_ci				src << "    imageStore(u_image1, 3*pos+0, " << type << "(t.x));\n";
1408e5c31af7Sopenharmony_ci				src << "    imageStore(u_image1, 3*pos+1, " << type << "(t.y));\n";
1409e5c31af7Sopenharmony_ci				src << "    imageStore(u_image1, 3*pos+2, " << type << "(t.z));\n";
1410e5c31af7Sopenharmony_ci			}
1411e5c31af7Sopenharmony_ci			else
1412e5c31af7Sopenharmony_ci				src << "    imageStore(u_image1, pos, t);\n";
1413e5c31af7Sopenharmony_ci		}
1414e5c31af7Sopenharmony_ci		else if (m_imageLoadStoreLodAMD)
1415e5c31af7Sopenharmony_ci		{
1416e5c31af7Sopenharmony_ci			src <<
1417e5c31af7Sopenharmony_ci				"    int pos = int(gl_GlobalInvocationID.x);\n";
1418e5c31af7Sopenharmony_ci
1419e5c31af7Sopenharmony_ci			for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1420e5c31af7Sopenharmony_ci			{
1421e5c31af7Sopenharmony_ci				std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1422e5c31af7Sopenharmony_ci				src << "    imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, " + xMaxSize + "-pos, " + de::toString(levelNdx) + "));\n";
1423e5c31af7Sopenharmony_ci			}
1424e5c31af7Sopenharmony_ci		}
1425e5c31af7Sopenharmony_ci		else
1426e5c31af7Sopenharmony_ci		{
1427e5c31af7Sopenharmony_ci			src <<
1428e5c31af7Sopenharmony_ci				"    int pos = int(gl_GlobalInvocationID.x);\n"
1429e5c31af7Sopenharmony_ci				"    imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n";
1430e5c31af7Sopenharmony_ci		}
1431e5c31af7Sopenharmony_ci		break;
1432e5c31af7Sopenharmony_ci	case 2:
1433e5c31af7Sopenharmony_ci		if (m_imageLoadStoreLodAMD)
1434e5c31af7Sopenharmony_ci		{
1435e5c31af7Sopenharmony_ci			src << "    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n";
1436e5c31af7Sopenharmony_ci
1437e5c31af7Sopenharmony_ci			for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1438e5c31af7Sopenharmony_ci			{
1439e5c31af7Sopenharmony_ci				std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1440e5c31af7Sopenharmony_ci				src << "    imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec2(" + xMaxSize + "-pos.x, pos.y), " + de::toString(levelNdx) + "));\n";
1441e5c31af7Sopenharmony_ci			}
1442e5c31af7Sopenharmony_ci
1443e5c31af7Sopenharmony_ci		}
1444e5c31af7Sopenharmony_ci		else
1445e5c31af7Sopenharmony_ci		{
1446e5c31af7Sopenharmony_ci			src <<
1447e5c31af7Sopenharmony_ci				"    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
1448e5c31af7Sopenharmony_ci				"    imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n";
1449e5c31af7Sopenharmony_ci		}
1450e5c31af7Sopenharmony_ci		break;
1451e5c31af7Sopenharmony_ci	case 3:
1452e5c31af7Sopenharmony_ci		if (m_imageLoadStoreLodAMD)
1453e5c31af7Sopenharmony_ci		{
1454e5c31af7Sopenharmony_ci			src << "    ivec3 pos = ivec3(gl_GlobalInvocationID);\n";
1455e5c31af7Sopenharmony_ci
1456e5c31af7Sopenharmony_ci			for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1457e5c31af7Sopenharmony_ci			{
1458e5c31af7Sopenharmony_ci				std::string xMaxSize = de::toString(deMax32(((m_texture.layerSize().x() >> levelNdx) - 1), 1u));
1459e5c31af7Sopenharmony_ci				src << "    imageStoreLodAMD(u_image1, pos, " + de::toString(levelNdx) + ", imageLoadLodAMD(u_image0, ivec3(" + xMaxSize + "-pos.x, pos.y, pos.z), " + de::toString(levelNdx) + "));\n";
1460e5c31af7Sopenharmony_ci			}
1461e5c31af7Sopenharmony_ci		}
1462e5c31af7Sopenharmony_ci		else
1463e5c31af7Sopenharmony_ci		{
1464e5c31af7Sopenharmony_ci			src <<
1465e5c31af7Sopenharmony_ci				"    ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
1466e5c31af7Sopenharmony_ci				"    imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n";
1467e5c31af7Sopenharmony_ci		}
1468e5c31af7Sopenharmony_ci		break;
1469e5c31af7Sopenharmony_ci	}
1470e5c31af7Sopenharmony_ci	src << "}\n";
1471e5c31af7Sopenharmony_ci
1472e5c31af7Sopenharmony_ci	programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1473e5c31af7Sopenharmony_ci}
1474e5c31af7Sopenharmony_ci
1475e5c31af7Sopenharmony_ci//! Load/store test base implementation
1476e5c31af7Sopenharmony_ciclass LoadStoreTestInstance : public BaseTestInstance
1477e5c31af7Sopenharmony_ci{
1478e5c31af7Sopenharmony_cipublic:
1479e5c31af7Sopenharmony_ci									LoadStoreTestInstance				(Context&			context,
1480e5c31af7Sopenharmony_ci																		 const Texture&		texture,
1481e5c31af7Sopenharmony_ci																		 const VkFormat		format,
1482e5c31af7Sopenharmony_ci																		 const VkFormat		imageFormat,
1483e5c31af7Sopenharmony_ci																		 const bool			declareImageFormatInShader,
1484e5c31af7Sopenharmony_ci																		 const bool			singleLayerBind,
1485e5c31af7Sopenharmony_ci																		 const bool			minalign,
1486e5c31af7Sopenharmony_ci																		 const bool			bufferLoadUniform);
1487e5c31af7Sopenharmony_ci
1488e5c31af7Sopenharmony_ciprotected:
1489e5c31af7Sopenharmony_ci	virtual BufferWithMemory*		getResultBuffer						(void) const = 0;	//!< Get the buffer that contains the result image
1490e5c31af7Sopenharmony_ci
1491e5c31af7Sopenharmony_ci	tcu::TestStatus					verifyResult						(void);
1492e5c31af7Sopenharmony_ci
1493e5c31af7Sopenharmony_ci	// Add empty implementations for functions that might be not needed
1494e5c31af7Sopenharmony_ci	void							commandBeforeCompute				(const VkCommandBuffer) {}
1495e5c31af7Sopenharmony_ci	void							commandBetweenShaderInvocations		(const VkCommandBuffer) {}
1496e5c31af7Sopenharmony_ci	void							commandAfterCompute					(const VkCommandBuffer) {}
1497e5c31af7Sopenharmony_ci
1498e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>	m_imageBuffer;		//!< Source data and helper buffer
1499e5c31af7Sopenharmony_ci	const VkDeviceSize				m_imageSizeBytes;
1500e5c31af7Sopenharmony_ci	const VkFormat					m_imageFormat;		//!< Image format (for storage, may be different than texture format)
1501e5c31af7Sopenharmony_ci	tcu::TextureLevel				m_referenceImage;	//!< Used as input data and later to verify result image
1502e5c31af7Sopenharmony_ci
1503e5c31af7Sopenharmony_ci	bool							m_bufferLoadUniform;
1504e5c31af7Sopenharmony_ci	VkDescriptorType				m_bufferLoadDescriptorType;
1505e5c31af7Sopenharmony_ci	VkBufferUsageFlagBits			m_bufferLoadUsageBit;
1506e5c31af7Sopenharmony_ci};
1507e5c31af7Sopenharmony_ci
1508e5c31af7Sopenharmony_ciLoadStoreTestInstance::LoadStoreTestInstance (Context&			context,
1509e5c31af7Sopenharmony_ci											  const Texture&	texture,
1510e5c31af7Sopenharmony_ci											  const VkFormat	format,
1511e5c31af7Sopenharmony_ci											  const VkFormat	imageFormat,
1512e5c31af7Sopenharmony_ci											  const bool		declareImageFormatInShader,
1513e5c31af7Sopenharmony_ci											  const bool		singleLayerBind,
1514e5c31af7Sopenharmony_ci											  const bool		minalign,
1515e5c31af7Sopenharmony_ci											  const bool		bufferLoadUniform)
1516e5c31af7Sopenharmony_ci	: BaseTestInstance		(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1517e5c31af7Sopenharmony_ci	, m_imageSizeBytes		(getImageSizeBytes(texture.size(), format))
1518e5c31af7Sopenharmony_ci	, m_imageFormat			(imageFormat)
1519e5c31af7Sopenharmony_ci	, m_referenceImage		(generateReferenceImage(texture.size(), imageFormat, format))
1520e5c31af7Sopenharmony_ci	, m_bufferLoadUniform	(bufferLoadUniform)
1521e5c31af7Sopenharmony_ci{
1522e5c31af7Sopenharmony_ci	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1523e5c31af7Sopenharmony_ci	const VkDevice			device		= m_context.getDevice();
1524e5c31af7Sopenharmony_ci	Allocator&				allocator	= m_context.getDefaultAllocator();
1525e5c31af7Sopenharmony_ci
1526e5c31af7Sopenharmony_ci	m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1527e5c31af7Sopenharmony_ci	m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1528e5c31af7Sopenharmony_ci
1529e5c31af7Sopenharmony_ci	// A helper buffer with enough space to hold the whole image.
1530e5c31af7Sopenharmony_ci
1531e5c31af7Sopenharmony_ci	m_imageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1532e5c31af7Sopenharmony_ci		vk, device, allocator,
1533e5c31af7Sopenharmony_ci		makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1534e5c31af7Sopenharmony_ci		MemoryRequirement::HostVisible));
1535e5c31af7Sopenharmony_ci
1536e5c31af7Sopenharmony_ci	// Copy reference data to buffer for subsequent upload to image.
1537e5c31af7Sopenharmony_ci
1538e5c31af7Sopenharmony_ci	const Allocation& alloc = m_imageBuffer->getAllocation();
1539e5c31af7Sopenharmony_ci	deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset, m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
1540e5c31af7Sopenharmony_ci	flushAlloc(vk, device, alloc);
1541e5c31af7Sopenharmony_ci}
1542e5c31af7Sopenharmony_ci
1543e5c31af7Sopenharmony_citcu::TestStatus LoadStoreTestInstance::verifyResult	(void)
1544e5c31af7Sopenharmony_ci{
1545e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1546e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1547e5c31af7Sopenharmony_ci
1548e5c31af7Sopenharmony_ci	// Apply the same transformation as done in the shader
1549e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
1550e5c31af7Sopenharmony_ci	flipHorizontally(reference);
1551e5c31af7Sopenharmony_ci
1552e5c31af7Sopenharmony_ci	const Allocation& alloc = getResultBuffer()->getAllocation();
1553e5c31af7Sopenharmony_ci	invalidateAlloc(vk, device, alloc);
1554e5c31af7Sopenharmony_ci	const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), (const char *)alloc.getHostPtr() + m_dstViewOffset);
1555e5c31af7Sopenharmony_ci
1556e5c31af7Sopenharmony_ci	if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
1557e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Passed");
1558e5c31af7Sopenharmony_ci	else
1559e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Image comparison failed");
1560e5c31af7Sopenharmony_ci}
1561e5c31af7Sopenharmony_ci
1562e5c31af7Sopenharmony_ci//! Load/store test for images
1563e5c31af7Sopenharmony_ciclass ImageLoadStoreTestInstance : public LoadStoreTestInstance
1564e5c31af7Sopenharmony_ci{
1565e5c31af7Sopenharmony_cipublic:
1566e5c31af7Sopenharmony_ci										ImageLoadStoreTestInstance			(Context&				context,
1567e5c31af7Sopenharmony_ci																			 const Texture&			texture,
1568e5c31af7Sopenharmony_ci																			 const VkFormat			format,
1569e5c31af7Sopenharmony_ci																			 const VkFormat			imageFormat,
1570e5c31af7Sopenharmony_ci																			 const VkImageTiling    tiling,
1571e5c31af7Sopenharmony_ci																			 const bool				declareImageFormatInShader,
1572e5c31af7Sopenharmony_ci																			 const bool				singleLayerBind,
1573e5c31af7Sopenharmony_ci																			 const bool				minalign,
1574e5c31af7Sopenharmony_ci																			 const bool				bufferLoadUniform);
1575e5c31af7Sopenharmony_ci
1576e5c31af7Sopenharmony_ciprotected:
1577e5c31af7Sopenharmony_ci	VkDescriptorSetLayout				prepareDescriptors					(void);
1578e5c31af7Sopenharmony_ci	void								commandBeforeCompute				(const VkCommandBuffer	cmdBuffer);
1579e5c31af7Sopenharmony_ci	void								commandBetweenShaderInvocations		(const VkCommandBuffer	cmdBuffer);
1580e5c31af7Sopenharmony_ci	void								commandAfterCompute					(const VkCommandBuffer	cmdBuffer);
1581e5c31af7Sopenharmony_ci
1582e5c31af7Sopenharmony_ci	void								commandBindDescriptorsForLayer		(const VkCommandBuffer	cmdBuffer,
1583e5c31af7Sopenharmony_ci																			 const VkPipelineLayout pipelineLayout,
1584e5c31af7Sopenharmony_ci																			 const int				layerNdx);
1585e5c31af7Sopenharmony_ci
1586e5c31af7Sopenharmony_ci	BufferWithMemory*					getResultBuffer						(void) const { return m_imageBuffer.get(); }
1587e5c31af7Sopenharmony_ci
1588e5c31af7Sopenharmony_ci	de::MovePtr<Image>					m_imageSrc;
1589e5c31af7Sopenharmony_ci	de::MovePtr<Image>					m_imageDst;
1590e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
1591e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>				m_descriptorPool;
1592e5c31af7Sopenharmony_ci	std::vector<SharedVkDescriptorSet> m_allDescriptorSets;
1593e5c31af7Sopenharmony_ci	std::vector<SharedVkImageView>     m_allSrcImageViews;
1594e5c31af7Sopenharmony_ci	std::vector<SharedVkImageView>     m_allDstImageViews;
1595e5c31af7Sopenharmony_ci};
1596e5c31af7Sopenharmony_ci
1597e5c31af7Sopenharmony_ciImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context&		context,
1598e5c31af7Sopenharmony_ci														const Texture&	texture,
1599e5c31af7Sopenharmony_ci														const VkFormat	format,
1600e5c31af7Sopenharmony_ci														const VkFormat	imageFormat,
1601e5c31af7Sopenharmony_ci														const VkImageTiling tiling,
1602e5c31af7Sopenharmony_ci														const bool		declareImageFormatInShader,
1603e5c31af7Sopenharmony_ci														const bool		singleLayerBind,
1604e5c31af7Sopenharmony_ci														const bool		minalign,
1605e5c31af7Sopenharmony_ci														const bool		bufferLoadUniform)
1606e5c31af7Sopenharmony_ci	: LoadStoreTestInstance	(context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1607e5c31af7Sopenharmony_ci	, m_allDescriptorSets	(texture.numLayers())
1608e5c31af7Sopenharmony_ci	, m_allSrcImageViews	(texture.numLayers())
1609e5c31af7Sopenharmony_ci	, m_allDstImageViews	(texture.numLayers())
1610e5c31af7Sopenharmony_ci{
1611e5c31af7Sopenharmony_ci	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1612e5c31af7Sopenharmony_ci	const VkDevice				device				= m_context.getDevice();
1613e5c31af7Sopenharmony_ci	Allocator&					allocator			= m_context.getDefaultAllocator();
1614e5c31af7Sopenharmony_ci	const VkImageCreateFlags	imageFlags			= (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1615e5c31af7Sopenharmony_ci
1616e5c31af7Sopenharmony_ci	m_imageSrc = de::MovePtr<Image>(new Image(
1617e5c31af7Sopenharmony_ci		vk, device, allocator,
1618e5c31af7Sopenharmony_ci		makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags, tiling),
1619e5c31af7Sopenharmony_ci		MemoryRequirement::Any));
1620e5c31af7Sopenharmony_ci
1621e5c31af7Sopenharmony_ci	m_imageDst = de::MovePtr<Image>(new Image(
1622e5c31af7Sopenharmony_ci		vk, device, allocator,
1623e5c31af7Sopenharmony_ci		makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags, tiling),
1624e5c31af7Sopenharmony_ci		MemoryRequirement::Any));
1625e5c31af7Sopenharmony_ci}
1626e5c31af7Sopenharmony_ci
1627e5c31af7Sopenharmony_ciVkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
1628e5c31af7Sopenharmony_ci{
1629e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1630e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1631e5c31af7Sopenharmony_ci
1632e5c31af7Sopenharmony_ci	const int numLayers = m_texture.numLayers();
1633e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1634e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1635e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1636e5c31af7Sopenharmony_ci		.build(vk, device);
1637e5c31af7Sopenharmony_ci
1638e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
1639e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1640e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1641e5c31af7Sopenharmony_ci		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1642e5c31af7Sopenharmony_ci
1643e5c31af7Sopenharmony_ci	if (m_singleLayerBind)
1644e5c31af7Sopenharmony_ci	{
1645e5c31af7Sopenharmony_ci		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1646e5c31af7Sopenharmony_ci		{
1647e5c31af7Sopenharmony_ci			const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1648e5c31af7Sopenharmony_ci			const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
1649e5c31af7Sopenharmony_ci
1650e5c31af7Sopenharmony_ci			m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1651e5c31af7Sopenharmony_ci			m_allSrcImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1652e5c31af7Sopenharmony_ci			m_allDstImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1653e5c31af7Sopenharmony_ci		}
1654e5c31af7Sopenharmony_ci	}
1655e5c31af7Sopenharmony_ci	else // bind all layers at once
1656e5c31af7Sopenharmony_ci	{
1657e5c31af7Sopenharmony_ci		const VkImageViewType viewType = mapImageViewType(m_texture.type());
1658e5c31af7Sopenharmony_ci		const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
1659e5c31af7Sopenharmony_ci
1660e5c31af7Sopenharmony_ci		m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1661e5c31af7Sopenharmony_ci		m_allSrcImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1662e5c31af7Sopenharmony_ci		m_allDstImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1663e5c31af7Sopenharmony_ci	}
1664e5c31af7Sopenharmony_ci
1665e5c31af7Sopenharmony_ci	return *m_descriptorSetLayout;  // not passing the ownership
1666e5c31af7Sopenharmony_ci}
1667e5c31af7Sopenharmony_ci
1668e5c31af7Sopenharmony_civoid ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1669e5c31af7Sopenharmony_ci{
1670e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1671e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1672e5c31af7Sopenharmony_ci
1673e5c31af7Sopenharmony_ci	const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1674e5c31af7Sopenharmony_ci	const VkImageView	  srcImageView	= **m_allSrcImageViews[layerNdx];
1675e5c31af7Sopenharmony_ci	const VkImageView	  dstImageView	= **m_allDstImageViews[layerNdx];
1676e5c31af7Sopenharmony_ci
1677e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1678e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1679e5c31af7Sopenharmony_ci
1680e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
1681e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1682e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1683e5c31af7Sopenharmony_ci		.update(vk, device);
1684e5c31af7Sopenharmony_ci	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1685e5c31af7Sopenharmony_ci}
1686e5c31af7Sopenharmony_ci
1687e5c31af7Sopenharmony_civoid ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1688e5c31af7Sopenharmony_ci{
1689e5c31af7Sopenharmony_ci	const DeviceInterface& vk = m_context.getDeviceInterface();
1690e5c31af7Sopenharmony_ci
1691e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
1692e5c31af7Sopenharmony_ci	{
1693e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier preCopyImageBarriers[] =
1694e5c31af7Sopenharmony_ci		{
1695e5c31af7Sopenharmony_ci			makeImageMemoryBarrier(
1696e5c31af7Sopenharmony_ci				0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1697e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1698e5c31af7Sopenharmony_ci				m_imageSrc->get(), fullImageSubresourceRange),
1699e5c31af7Sopenharmony_ci			makeImageMemoryBarrier(
1700e5c31af7Sopenharmony_ci				0u, VK_ACCESS_SHADER_WRITE_BIT,
1701e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1702e5c31af7Sopenharmony_ci				m_imageDst->get(), fullImageSubresourceRange)
1703e5c31af7Sopenharmony_ci		};
1704e5c31af7Sopenharmony_ci
1705e5c31af7Sopenharmony_ci		const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1706e5c31af7Sopenharmony_ci			VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1707e5c31af7Sopenharmony_ci			m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1708e5c31af7Sopenharmony_ci
1709e5c31af7Sopenharmony_ci		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1710e5c31af7Sopenharmony_ci			(VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1711e5c31af7Sopenharmony_ci	}
1712e5c31af7Sopenharmony_ci	{
1713e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1714e5c31af7Sopenharmony_ci			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1715e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
1716e5c31af7Sopenharmony_ci			m_imageSrc->get(), fullImageSubresourceRange);
1717e5c31af7Sopenharmony_ci
1718e5c31af7Sopenharmony_ci		const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_ci		vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
1721e5c31af7Sopenharmony_ci		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
1722e5c31af7Sopenharmony_ci	}
1723e5c31af7Sopenharmony_ci}
1724e5c31af7Sopenharmony_ci
1725e5c31af7Sopenharmony_civoid ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
1726e5c31af7Sopenharmony_ci{
1727e5c31af7Sopenharmony_ci	commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
1728e5c31af7Sopenharmony_ci}
1729e5c31af7Sopenharmony_ci
1730e5c31af7Sopenharmony_civoid ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
1731e5c31af7Sopenharmony_ci{
1732e5c31af7Sopenharmony_ci	commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
1733e5c31af7Sopenharmony_ci}
1734e5c31af7Sopenharmony_ci
1735e5c31af7Sopenharmony_ci//! Load/store Lod AMD test for images
1736e5c31af7Sopenharmony_ciclass ImageLoadStoreLodAMDTestInstance : public BaseTestInstance
1737e5c31af7Sopenharmony_ci{
1738e5c31af7Sopenharmony_cipublic:
1739e5c31af7Sopenharmony_ci										ImageLoadStoreLodAMDTestInstance	(Context&				context,
1740e5c31af7Sopenharmony_ci																			 const Texture&			texture,
1741e5c31af7Sopenharmony_ci																			 const VkFormat			format,
1742e5c31af7Sopenharmony_ci																			 const VkFormat			imageFormat,
1743e5c31af7Sopenharmony_ci																			 const bool				declareImageFormatInShader,
1744e5c31af7Sopenharmony_ci																			 const bool				singleLayerBind,
1745e5c31af7Sopenharmony_ci																			 const bool				minalign,
1746e5c31af7Sopenharmony_ci																			 const bool				bufferLoadUniform);
1747e5c31af7Sopenharmony_ci
1748e5c31af7Sopenharmony_ciprotected:
1749e5c31af7Sopenharmony_ci	VkDescriptorSetLayout				prepareDescriptors					(void);
1750e5c31af7Sopenharmony_ci	void								commandBeforeCompute				(const VkCommandBuffer	cmdBuffer);
1751e5c31af7Sopenharmony_ci	void								commandBetweenShaderInvocations		(const VkCommandBuffer	cmdBuffer);
1752e5c31af7Sopenharmony_ci	void								commandAfterCompute					(const VkCommandBuffer	cmdBuffer);
1753e5c31af7Sopenharmony_ci
1754e5c31af7Sopenharmony_ci	void								commandBindDescriptorsForLayer		(const VkCommandBuffer	cmdBuffer,
1755e5c31af7Sopenharmony_ci																			 const VkPipelineLayout pipelineLayout,
1756e5c31af7Sopenharmony_ci																			 const int				layerNdx);
1757e5c31af7Sopenharmony_ci
1758e5c31af7Sopenharmony_ci	BufferWithMemory*					getResultBuffer						(void) const { return m_imageBuffer.get(); }
1759e5c31af7Sopenharmony_ci	tcu::TestStatus						verifyResult						(void);
1760e5c31af7Sopenharmony_ci
1761e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>		m_imageBuffer;		//!< Source data and helper buffer
1762e5c31af7Sopenharmony_ci	const VkDeviceSize					m_imageSizeBytes;
1763e5c31af7Sopenharmony_ci	const VkFormat						m_imageFormat;		//!< Image format (for storage, may be different than texture format)
1764e5c31af7Sopenharmony_ci	std::vector<tcu::TextureLevel>		m_referenceImages;	//!< Used as input data and later to verify result image
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ci	bool								m_bufferLoadUniform;
1767e5c31af7Sopenharmony_ci	VkDescriptorType					m_bufferLoadDescriptorType;
1768e5c31af7Sopenharmony_ci	VkBufferUsageFlagBits				m_bufferLoadUsageBit;
1769e5c31af7Sopenharmony_ci
1770e5c31af7Sopenharmony_ci	de::MovePtr<Image>					m_imageSrc;
1771e5c31af7Sopenharmony_ci	de::MovePtr<Image>					m_imageDst;
1772e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
1773e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>				m_descriptorPool;
1774e5c31af7Sopenharmony_ci	std::vector<SharedVkDescriptorSet>	m_allDescriptorSets;
1775e5c31af7Sopenharmony_ci	std::vector<SharedVkImageView>		m_allSrcImageViews;
1776e5c31af7Sopenharmony_ci	std::vector<SharedVkImageView>		m_allDstImageViews;
1777e5c31af7Sopenharmony_ci
1778e5c31af7Sopenharmony_ci};
1779e5c31af7Sopenharmony_ci
1780e5c31af7Sopenharmony_ciImageLoadStoreLodAMDTestInstance::ImageLoadStoreLodAMDTestInstance (Context&		context,
1781e5c31af7Sopenharmony_ci																	const Texture&	texture,
1782e5c31af7Sopenharmony_ci																	const VkFormat	format,
1783e5c31af7Sopenharmony_ci																	const VkFormat	imageFormat,
1784e5c31af7Sopenharmony_ci																	const bool		declareImageFormatInShader,
1785e5c31af7Sopenharmony_ci																	const bool		singleLayerBind,
1786e5c31af7Sopenharmony_ci																	const bool		minalign,
1787e5c31af7Sopenharmony_ci																	const bool		bufferLoadUniform)
1788e5c31af7Sopenharmony_ci	: BaseTestInstance			(context, texture, format, declareImageFormatInShader, singleLayerBind, minalign, bufferLoadUniform)
1789e5c31af7Sopenharmony_ci	, m_imageSizeBytes			(getMipmapImageTotalSizeBytes(texture, format))
1790e5c31af7Sopenharmony_ci	, m_imageFormat				(imageFormat)
1791e5c31af7Sopenharmony_ci	, m_bufferLoadUniform		(bufferLoadUniform)
1792e5c31af7Sopenharmony_ci	, m_allDescriptorSets		(texture.numLayers())
1793e5c31af7Sopenharmony_ci	, m_allSrcImageViews		(texture.numLayers())
1794e5c31af7Sopenharmony_ci	, m_allDstImageViews		(texture.numLayers())
1795e5c31af7Sopenharmony_ci{
1796e5c31af7Sopenharmony_ci	const DeviceInterface&		vk					= m_context.getDeviceInterface();
1797e5c31af7Sopenharmony_ci	const VkDevice				device				= m_context.getDevice();
1798e5c31af7Sopenharmony_ci	Allocator&					allocator			= m_context.getDefaultAllocator();
1799e5c31af7Sopenharmony_ci	const VkImageCreateFlags	imageFlags			= (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
1800e5c31af7Sopenharmony_ci
1801e5c31af7Sopenharmony_ci	const VkSampleCountFlagBits samples = static_cast<VkSampleCountFlagBits>(m_texture.numSamples());	// integer and bit mask are aligned, so we can cast like this
1802e5c31af7Sopenharmony_ci
1803e5c31af7Sopenharmony_ci	for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1804e5c31af7Sopenharmony_ci	{
1805e5c31af7Sopenharmony_ci		tcu::TextureLevel referenceImage = generateReferenceImage(texture.size(levelNdx), imageFormat, format);
1806e5c31af7Sopenharmony_ci		m_referenceImages.push_back(referenceImage);
1807e5c31af7Sopenharmony_ci	}
1808e5c31af7Sopenharmony_ci
1809e5c31af7Sopenharmony_ci	m_bufferLoadDescriptorType = m_bufferLoadUniform ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1810e5c31af7Sopenharmony_ci	m_bufferLoadUsageBit = m_bufferLoadUniform ? VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
1811e5c31af7Sopenharmony_ci
1812e5c31af7Sopenharmony_ci	// A helper buffer with enough space to hold the whole image.
1813e5c31af7Sopenharmony_ci	m_imageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
1814e5c31af7Sopenharmony_ci												   vk, device, allocator,
1815e5c31af7Sopenharmony_ci												   makeBufferCreateInfo(m_imageSizeBytes + m_srcViewOffset, m_bufferLoadUsageBit | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
1816e5c31af7Sopenharmony_ci												   MemoryRequirement::HostVisible));
1817e5c31af7Sopenharmony_ci
1818e5c31af7Sopenharmony_ci	// Copy reference data to buffer for subsequent upload to image.
1819e5c31af7Sopenharmony_ci	{
1820e5c31af7Sopenharmony_ci		const Allocation& alloc = m_imageBuffer->getAllocation();
1821e5c31af7Sopenharmony_ci		VkDeviceSize bufferOffset = 0u;
1822e5c31af7Sopenharmony_ci		for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1823e5c31af7Sopenharmony_ci		{
1824e5c31af7Sopenharmony_ci			deMemcpy((char *)alloc.getHostPtr() + m_srcViewOffset + bufferOffset, m_referenceImages[levelNdx].getAccess().getDataPtr(), static_cast<size_t>(getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx)));
1825e5c31af7Sopenharmony_ci			bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1826e5c31af7Sopenharmony_ci		}
1827e5c31af7Sopenharmony_ci		flushAlloc(vk, device, alloc);
1828e5c31af7Sopenharmony_ci	}
1829e5c31af7Sopenharmony_ci
1830e5c31af7Sopenharmony_ci	{
1831e5c31af7Sopenharmony_ci		const VkImageCreateInfo imageParamsSrc =
1832e5c31af7Sopenharmony_ci		{
1833e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
1834e5c31af7Sopenharmony_ci			DE_NULL,																							// const void*				pNext;
1835e5c31af7Sopenharmony_ci			(isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags,	// VkImageCreateFlags		flags;
1836e5c31af7Sopenharmony_ci			mapImageType(m_texture.type()),																		// VkImageType				imageType;
1837e5c31af7Sopenharmony_ci			m_imageFormat,																						// VkFormat					format;
1838e5c31af7Sopenharmony_ci			makeExtent3D(m_texture.layerSize()),																// VkExtent3D				extent;
1839e5c31af7Sopenharmony_ci			(deUint32)m_texture.numMipmapLevels(),																// deUint32					mipLevels;
1840e5c31af7Sopenharmony_ci			(deUint32)m_texture.numLayers(),																	// deUint32					arrayLayers;
1841e5c31af7Sopenharmony_ci			samples,																							// VkSampleCountFlagBits	samples;
1842e5c31af7Sopenharmony_ci			VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
1843e5c31af7Sopenharmony_ci			VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,										// VkImageUsageFlags		usage;
1844e5c31af7Sopenharmony_ci			VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
1845e5c31af7Sopenharmony_ci			0u,																									// deUint32					queueFamilyIndexCount;
1846e5c31af7Sopenharmony_ci			DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
1847e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_UNDEFINED,																			// VkImageLayout			initialLayout;
1848e5c31af7Sopenharmony_ci		};
1849e5c31af7Sopenharmony_ci
1850e5c31af7Sopenharmony_ci		m_imageSrc = de::MovePtr<Image>(new Image(
1851e5c31af7Sopenharmony_ci												  vk, device, allocator,
1852e5c31af7Sopenharmony_ci												  imageParamsSrc,
1853e5c31af7Sopenharmony_ci												  MemoryRequirement::Any));
1854e5c31af7Sopenharmony_ci	}
1855e5c31af7Sopenharmony_ci
1856e5c31af7Sopenharmony_ci	{
1857e5c31af7Sopenharmony_ci		const VkImageCreateInfo imageParamsDst =
1858e5c31af7Sopenharmony_ci		{
1859e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,																// VkStructureType			sType;
1860e5c31af7Sopenharmony_ci			DE_NULL,																							// const void*				pNext;
1861e5c31af7Sopenharmony_ci			(isCube(m_texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u) | imageFlags,	// VkImageCreateFlags		flags;
1862e5c31af7Sopenharmony_ci			mapImageType(m_texture.type()),																		// VkImageType				imageType;
1863e5c31af7Sopenharmony_ci			m_imageFormat,																						// VkFormat					format;
1864e5c31af7Sopenharmony_ci			makeExtent3D(m_texture.layerSize()),																// VkExtent3D				extent;
1865e5c31af7Sopenharmony_ci			(deUint32)m_texture.numMipmapLevels(),																// deUint32					mipLevels;
1866e5c31af7Sopenharmony_ci			(deUint32)m_texture.numLayers(),																	// deUint32					arrayLayers;
1867e5c31af7Sopenharmony_ci			samples,																							// VkSampleCountFlagBits	samples;
1868e5c31af7Sopenharmony_ci			VK_IMAGE_TILING_OPTIMAL,																			// VkImageTiling			tiling;
1869e5c31af7Sopenharmony_ci			VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,										// VkImageUsageFlags		usage;
1870e5c31af7Sopenharmony_ci			VK_SHARING_MODE_EXCLUSIVE,																			// VkSharingMode			sharingMode;
1871e5c31af7Sopenharmony_ci			0u,																									// deUint32					queueFamilyIndexCount;
1872e5c31af7Sopenharmony_ci			DE_NULL,																							// const deUint32*			pQueueFamilyIndices;
1873e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_UNDEFINED,																			// VkImageLayout			initialLayout;
1874e5c31af7Sopenharmony_ci		};
1875e5c31af7Sopenharmony_ci
1876e5c31af7Sopenharmony_ci		m_imageDst = de::MovePtr<Image>(new Image(
1877e5c31af7Sopenharmony_ci												  vk, device, allocator,
1878e5c31af7Sopenharmony_ci												  imageParamsDst,
1879e5c31af7Sopenharmony_ci												  MemoryRequirement::Any));
1880e5c31af7Sopenharmony_ci	}
1881e5c31af7Sopenharmony_ci}
1882e5c31af7Sopenharmony_ci
1883e5c31af7Sopenharmony_citcu::TestStatus ImageLoadStoreLodAMDTestInstance::verifyResult	(void)
1884e5c31af7Sopenharmony_ci{
1885e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1886e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1887e5c31af7Sopenharmony_ci
1888e5c31af7Sopenharmony_ci	const Allocation& alloc = getResultBuffer()->getAllocation();
1889e5c31af7Sopenharmony_ci	invalidateAlloc(vk, device, alloc);
1890e5c31af7Sopenharmony_ci
1891e5c31af7Sopenharmony_ci    VkDeviceSize bufferOffset = 0;
1892e5c31af7Sopenharmony_ci	for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
1893e5c31af7Sopenharmony_ci	{
1894e5c31af7Sopenharmony_ci		// Apply the same transformation as done in the shader
1895e5c31af7Sopenharmony_ci		const tcu::PixelBufferAccess reference = m_referenceImages[levelNdx].getAccess();
1896e5c31af7Sopenharmony_ci		flipHorizontally(reference);
1897e5c31af7Sopenharmony_ci
1898e5c31af7Sopenharmony_ci		const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(levelNdx), (const char *)alloc.getHostPtr() + m_dstViewOffset + bufferOffset);
1899e5c31af7Sopenharmony_ci
1900e5c31af7Sopenharmony_ci		if (!comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result, levelNdx))
1901e5c31af7Sopenharmony_ci		{
1902e5c31af7Sopenharmony_ci			std::ostringstream errorMessage;
1903e5c31af7Sopenharmony_ci			errorMessage << "Image Level " << levelNdx << " comparison failed";
1904e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(errorMessage.str());
1905e5c31af7Sopenharmony_ci		}
1906e5c31af7Sopenharmony_ci		bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
1907e5c31af7Sopenharmony_ci	}
1908e5c31af7Sopenharmony_ci
1909e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Passed");
1910e5c31af7Sopenharmony_ci}
1911e5c31af7Sopenharmony_ci
1912e5c31af7Sopenharmony_ciVkDescriptorSetLayout ImageLoadStoreLodAMDTestInstance::prepareDescriptors (void)
1913e5c31af7Sopenharmony_ci{
1914e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1915e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1916e5c31af7Sopenharmony_ci
1917e5c31af7Sopenharmony_ci	const int numLayers = m_texture.numLayers();
1918e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1919e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1920e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1921e5c31af7Sopenharmony_ci		.build(vk, device);
1922e5c31af7Sopenharmony_ci
1923e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
1924e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1925e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
1926e5c31af7Sopenharmony_ci		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
1927e5c31af7Sopenharmony_ci
1928e5c31af7Sopenharmony_ci	if (m_singleLayerBind)
1929e5c31af7Sopenharmony_ci	{
1930e5c31af7Sopenharmony_ci		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1931e5c31af7Sopenharmony_ci		{
1932e5c31af7Sopenharmony_ci			const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
1933e5c31af7Sopenharmony_ci			const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), layerNdx, 1u);
1934e5c31af7Sopenharmony_ci
1935e5c31af7Sopenharmony_ci			m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1936e5c31af7Sopenharmony_ci			m_allSrcImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1937e5c31af7Sopenharmony_ci			m_allDstImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1938e5c31af7Sopenharmony_ci		}
1939e5c31af7Sopenharmony_ci	}
1940e5c31af7Sopenharmony_ci	else // bind all layers at once
1941e5c31af7Sopenharmony_ci	{
1942e5c31af7Sopenharmony_ci		const VkImageViewType viewType = mapImageViewType(m_texture.type());
1943e5c31af7Sopenharmony_ci		const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, numLayers);
1944e5c31af7Sopenharmony_ci
1945e5c31af7Sopenharmony_ci		m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
1946e5c31af7Sopenharmony_ci		m_allSrcImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
1947e5c31af7Sopenharmony_ci		m_allDstImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
1948e5c31af7Sopenharmony_ci	}
1949e5c31af7Sopenharmony_ci
1950e5c31af7Sopenharmony_ci	return *m_descriptorSetLayout;  // not passing the ownership
1951e5c31af7Sopenharmony_ci}
1952e5c31af7Sopenharmony_ci
1953e5c31af7Sopenharmony_civoid ImageLoadStoreLodAMDTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
1954e5c31af7Sopenharmony_ci{
1955e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
1956e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
1957e5c31af7Sopenharmony_ci
1958e5c31af7Sopenharmony_ci	const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
1959e5c31af7Sopenharmony_ci	const VkImageView	  srcImageView	= **m_allSrcImageViews[layerNdx];
1960e5c31af7Sopenharmony_ci	const VkImageView	  dstImageView	= **m_allDstImageViews[layerNdx];
1961e5c31af7Sopenharmony_ci
1962e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
1963e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
1964e5c31af7Sopenharmony_ci
1965e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
1966e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
1967e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
1968e5c31af7Sopenharmony_ci		.update(vk, device);
1969e5c31af7Sopenharmony_ci	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
1970e5c31af7Sopenharmony_ci}
1971e5c31af7Sopenharmony_ci
1972e5c31af7Sopenharmony_civoid ImageLoadStoreLodAMDTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
1973e5c31af7Sopenharmony_ci{
1974e5c31af7Sopenharmony_ci	const DeviceInterface& vk = m_context.getDeviceInterface();
1975e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, m_texture.numMipmapLevels(), 0u, m_texture.numLayers());
1976e5c31af7Sopenharmony_ci	{
1977e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier preCopyImageBarriers[] =
1978e5c31af7Sopenharmony_ci		{
1979e5c31af7Sopenharmony_ci			makeImageMemoryBarrier(
1980e5c31af7Sopenharmony_ci				0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1981e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1982e5c31af7Sopenharmony_ci				m_imageSrc->get(), fullImageSubresourceRange),
1983e5c31af7Sopenharmony_ci			makeImageMemoryBarrier(
1984e5c31af7Sopenharmony_ci				0u, VK_ACCESS_SHADER_WRITE_BIT,
1985e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1986e5c31af7Sopenharmony_ci				m_imageDst->get(), fullImageSubresourceRange)
1987e5c31af7Sopenharmony_ci		};
1988e5c31af7Sopenharmony_ci
1989e5c31af7Sopenharmony_ci		const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
1990e5c31af7Sopenharmony_ci			VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1991e5c31af7Sopenharmony_ci			m_imageBuffer->get(), 0ull, m_imageSizeBytes + m_srcViewOffset);
1992e5c31af7Sopenharmony_ci
1993e5c31af7Sopenharmony_ci		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
1994e5c31af7Sopenharmony_ci			(VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
1995e5c31af7Sopenharmony_ci	}
1996e5c31af7Sopenharmony_ci	{
1997e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
1998e5c31af7Sopenharmony_ci			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1999e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2000e5c31af7Sopenharmony_ci			m_imageSrc->get(), fullImageSubresourceRange);
2001e5c31af7Sopenharmony_ci
2002e5c31af7Sopenharmony_ci		std::vector<VkBufferImageCopy> copyRegions;
2003e5c31af7Sopenharmony_ci		VkDeviceSize bufferOffset = 0u;
2004e5c31af7Sopenharmony_ci		for (deInt32 levelNdx = 0; levelNdx < m_texture.numMipmapLevels(); levelNdx++)
2005e5c31af7Sopenharmony_ci		{
2006e5c31af7Sopenharmony_ci			const VkBufferImageCopy copyParams =
2007e5c31af7Sopenharmony_ci			{
2008e5c31af7Sopenharmony_ci				bufferOffset,																					//	VkDeviceSize				bufferOffset;
2009e5c31af7Sopenharmony_ci				0u,																								//	deUint32					bufferRowLength;
2010e5c31af7Sopenharmony_ci				0u,																								//	deUint32					bufferImageHeight;
2011e5c31af7Sopenharmony_ci				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, 0u, m_texture.numLayers()),		//	VkImageSubresourceLayers	imageSubresource;
2012e5c31af7Sopenharmony_ci				makeOffset3D(0, 0, 0),																			//	VkOffset3D					imageOffset;
2013e5c31af7Sopenharmony_ci				makeExtent3D(m_texture.layerSize(levelNdx)),													//	VkExtent3D					imageExtent;
2014e5c31af7Sopenharmony_ci			};
2015e5c31af7Sopenharmony_ci			copyRegions.push_back(copyParams);
2016e5c31af7Sopenharmony_ci			bufferOffset += getMipmapLevelImageSizeBytes(m_texture, m_imageFormat, levelNdx);
2017e5c31af7Sopenharmony_ci		}
2018e5c31af7Sopenharmony_ci
2019e5c31af7Sopenharmony_ci		vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32) copyRegions.size(), copyRegions.data());
2020e5c31af7Sopenharmony_ci		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
2021e5c31af7Sopenharmony_ci	}
2022e5c31af7Sopenharmony_ci}
2023e5c31af7Sopenharmony_ci
2024e5c31af7Sopenharmony_civoid ImageLoadStoreLodAMDTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
2025e5c31af7Sopenharmony_ci{
2026e5c31af7Sopenharmony_ci	commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2027e5c31af7Sopenharmony_ci}
2028e5c31af7Sopenharmony_ci
2029e5c31af7Sopenharmony_civoid ImageLoadStoreLodAMDTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2030e5c31af7Sopenharmony_ci{
2031e5c31af7Sopenharmony_ci	commandCopyMipmapImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageFormat, m_imageBuffer->get(), m_imageSizeBytes, m_texture);
2032e5c31af7Sopenharmony_ci}
2033e5c31af7Sopenharmony_ci
2034e5c31af7Sopenharmony_ci//! Load/store test for buffers
2035e5c31af7Sopenharmony_ciclass BufferLoadStoreTestInstance : public LoadStoreTestInstance
2036e5c31af7Sopenharmony_ci{
2037e5c31af7Sopenharmony_cipublic:
2038e5c31af7Sopenharmony_ci									BufferLoadStoreTestInstance		(Context&				context,
2039e5c31af7Sopenharmony_ci																	 const Texture&			texture,
2040e5c31af7Sopenharmony_ci																	 const VkFormat			format,
2041e5c31af7Sopenharmony_ci																	 const VkFormat			imageFormat,
2042e5c31af7Sopenharmony_ci																	 const bool				declareImageFormatInShader,
2043e5c31af7Sopenharmony_ci																	 const bool				minalign,
2044e5c31af7Sopenharmony_ci																	 const bool				bufferLoadUniform);
2045e5c31af7Sopenharmony_ci
2046e5c31af7Sopenharmony_ciprotected:
2047e5c31af7Sopenharmony_ci	VkDescriptorSetLayout			prepareDescriptors				(void);
2048e5c31af7Sopenharmony_ci	void							commandAfterCompute				(const VkCommandBuffer	cmdBuffer);
2049e5c31af7Sopenharmony_ci
2050e5c31af7Sopenharmony_ci	void							commandBindDescriptorsForLayer	(const VkCommandBuffer	cmdBuffer,
2051e5c31af7Sopenharmony_ci																	 const VkPipelineLayout pipelineLayout,
2052e5c31af7Sopenharmony_ci																	 const int				layerNdx);
2053e5c31af7Sopenharmony_ci
2054e5c31af7Sopenharmony_ci	BufferWithMemory*				getResultBuffer					(void) const { return m_imageBufferDst.get(); }
2055e5c31af7Sopenharmony_ci
2056e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>	m_imageBufferDst;
2057e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
2058e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>			m_descriptorPool;
2059e5c31af7Sopenharmony_ci	Move<VkDescriptorSet>			m_descriptorSet;
2060e5c31af7Sopenharmony_ci	Move<VkBufferView>				m_bufferViewSrc;
2061e5c31af7Sopenharmony_ci	Move<VkBufferView>				m_bufferViewDst;
2062e5c31af7Sopenharmony_ci};
2063e5c31af7Sopenharmony_ci
2064e5c31af7Sopenharmony_ciBufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context&			context,
2065e5c31af7Sopenharmony_ci														  const Texture&	texture,
2066e5c31af7Sopenharmony_ci														  const VkFormat	format,
2067e5c31af7Sopenharmony_ci														  const VkFormat	imageFormat,
2068e5c31af7Sopenharmony_ci														  const bool		declareImageFormatInShader,
2069e5c31af7Sopenharmony_ci														  const bool		minalign,
2070e5c31af7Sopenharmony_ci														  const bool		bufferLoadUniform)
2071e5c31af7Sopenharmony_ci	: LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false, minalign, bufferLoadUniform)
2072e5c31af7Sopenharmony_ci{
2073e5c31af7Sopenharmony_ci	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2074e5c31af7Sopenharmony_ci	const VkDevice			device		= m_context.getDevice();
2075e5c31af7Sopenharmony_ci	Allocator&				allocator	= m_context.getDefaultAllocator();
2076e5c31af7Sopenharmony_ci
2077e5c31af7Sopenharmony_ci	// Create a destination buffer.
2078e5c31af7Sopenharmony_ci
2079e5c31af7Sopenharmony_ci	m_imageBufferDst = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
2080e5c31af7Sopenharmony_ci		vk, device, allocator,
2081e5c31af7Sopenharmony_ci		makeBufferCreateInfo(m_imageSizeBytes + m_dstViewOffset, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
2082e5c31af7Sopenharmony_ci		MemoryRequirement::HostVisible));
2083e5c31af7Sopenharmony_ci}
2084e5c31af7Sopenharmony_ci
2085e5c31af7Sopenharmony_ciVkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
2086e5c31af7Sopenharmony_ci{
2087e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
2088e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
2089e5c31af7Sopenharmony_ci
2090e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2091e5c31af7Sopenharmony_ci		.addSingleBinding(m_bufferLoadDescriptorType, VK_SHADER_STAGE_COMPUTE_BIT)
2092e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2093e5c31af7Sopenharmony_ci		.build(vk, device);
2094e5c31af7Sopenharmony_ci
2095e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
2096e5c31af7Sopenharmony_ci		.addType(m_bufferLoadDescriptorType)
2097e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
2098e5c31af7Sopenharmony_ci		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2099e5c31af7Sopenharmony_ci
2100e5c31af7Sopenharmony_ci	VkFormat dstFormat = formatHasThreeComponents(m_format) ? getSingleComponentFormat(m_format) : m_format;
2101e5c31af7Sopenharmony_ci
2102e5c31af7Sopenharmony_ci	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
2103e5c31af7Sopenharmony_ci	m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, m_srcViewOffset, m_imageSizeBytes);
2104e5c31af7Sopenharmony_ci	m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), dstFormat, m_dstViewOffset, m_imageSizeBytes);
2105e5c31af7Sopenharmony_ci
2106e5c31af7Sopenharmony_ci	return *m_descriptorSetLayout;  // not passing the ownership
2107e5c31af7Sopenharmony_ci}
2108e5c31af7Sopenharmony_ci
2109e5c31af7Sopenharmony_civoid BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2110e5c31af7Sopenharmony_ci{
2111e5c31af7Sopenharmony_ci	DE_ASSERT(layerNdx == 0);
2112e5c31af7Sopenharmony_ci	DE_UNREF(layerNdx);
2113e5c31af7Sopenharmony_ci
2114e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
2115e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
2116e5c31af7Sopenharmony_ci
2117e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
2118e5c31af7Sopenharmony_ci		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), m_bufferLoadDescriptorType, &m_bufferViewSrc.get())
2119e5c31af7Sopenharmony_ci		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
2120e5c31af7Sopenharmony_ci		.update(vk, device);
2121e5c31af7Sopenharmony_ci	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
2122e5c31af7Sopenharmony_ci}
2123e5c31af7Sopenharmony_ci
2124e5c31af7Sopenharmony_civoid BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2125e5c31af7Sopenharmony_ci{
2126e5c31af7Sopenharmony_ci	commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes + m_dstViewOffset);
2127e5c31af7Sopenharmony_ci}
2128e5c31af7Sopenharmony_ci
2129e5c31af7Sopenharmony_ciTestInstance* StoreTest::createInstance (Context& context) const
2130e5c31af7Sopenharmony_ci{
2131e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER)
2132e5c31af7Sopenharmony_ci		return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_minalign, m_storeConstantValue);
2133e5c31af7Sopenharmony_ci	else
2134e5c31af7Sopenharmony_ci		return new ImageStoreTestInstance(context, m_texture, m_format, m_tiling, m_declareImageFormatInShader, m_singleLayerBind, m_minalign, m_storeConstantValue);
2135e5c31af7Sopenharmony_ci}
2136e5c31af7Sopenharmony_ci
2137e5c31af7Sopenharmony_ciTestInstance* LoadStoreTest::createInstance (Context& context) const
2138e5c31af7Sopenharmony_ci{
2139e5c31af7Sopenharmony_ci	if (m_imageLoadStoreLodAMD)
2140e5c31af7Sopenharmony_ci		return new ImageLoadStoreLodAMDTestInstance(context, m_texture, m_format, m_imageFormat, m_declareFormatInShaderReads, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
2141e5c31af7Sopenharmony_ci
2142e5c31af7Sopenharmony_ci	if (m_texture.type() == IMAGE_TYPE_BUFFER)
2143e5c31af7Sopenharmony_ci		return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareFormatInShaderReads, m_minalign, m_bufferLoadUniform);
2144e5c31af7Sopenharmony_ci	else
2145e5c31af7Sopenharmony_ci		return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_tiling, m_declareFormatInShaderReads, m_singleLayerBind, m_minalign, m_bufferLoadUniform);
2146e5c31af7Sopenharmony_ci}
2147e5c31af7Sopenharmony_ci
2148e5c31af7Sopenharmony_ciclass ImageExtendOperandTestInstance : public BaseTestInstance
2149e5c31af7Sopenharmony_ci{
2150e5c31af7Sopenharmony_cipublic:
2151e5c31af7Sopenharmony_ci									ImageExtendOperandTestInstance			(Context&				context,
2152e5c31af7Sopenharmony_ci																			 const Texture&			texture,
2153e5c31af7Sopenharmony_ci																			 const VkFormat			readFormat,
2154e5c31af7Sopenharmony_ci																			 const VkFormat			writeFormat,
2155e5c31af7Sopenharmony_ci																			 bool					relaxedPrecision);
2156e5c31af7Sopenharmony_ci
2157e5c31af7Sopenharmony_ci	virtual							~ImageExtendOperandTestInstance			(void) {}
2158e5c31af7Sopenharmony_ci
2159e5c31af7Sopenharmony_ciprotected:
2160e5c31af7Sopenharmony_ci
2161e5c31af7Sopenharmony_ci	VkDescriptorSetLayout			prepareDescriptors						(void);
2162e5c31af7Sopenharmony_ci	void							commandBeforeCompute					(const VkCommandBuffer	cmdBuffer);
2163e5c31af7Sopenharmony_ci	void							commandBetweenShaderInvocations			(const VkCommandBuffer	cmdBuffer);
2164e5c31af7Sopenharmony_ci	void							commandAfterCompute						(const VkCommandBuffer	cmdBuffer);
2165e5c31af7Sopenharmony_ci
2166e5c31af7Sopenharmony_ci	void							commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
2167e5c31af7Sopenharmony_ci																			 const VkPipelineLayout pipelineLayout,
2168e5c31af7Sopenharmony_ci																			 const int				layerNdx);
2169e5c31af7Sopenharmony_ci
2170e5c31af7Sopenharmony_ci	tcu::TestStatus					verifyResult							(void);
2171e5c31af7Sopenharmony_ci
2172e5c31af7Sopenharmony_ciprotected:
2173e5c31af7Sopenharmony_ci
2174e5c31af7Sopenharmony_ci	bool							m_isSigned;
2175e5c31af7Sopenharmony_ci	tcu::TextureLevel				m_inputImageData;
2176e5c31af7Sopenharmony_ci
2177e5c31af7Sopenharmony_ci	de::MovePtr<Image>				m_imageSrc;				// source image
2178e5c31af7Sopenharmony_ci	SharedVkImageView				m_imageSrcView;
2179e5c31af7Sopenharmony_ci	VkDeviceSize					m_imageSrcSize;
2180e5c31af7Sopenharmony_ci
2181e5c31af7Sopenharmony_ci	de::MovePtr<Image>				m_imageDst;				// dest image
2182e5c31af7Sopenharmony_ci	SharedVkImageView				m_imageDstView;
2183e5c31af7Sopenharmony_ci	VkFormat						m_imageDstFormat;
2184e5c31af7Sopenharmony_ci	VkDeviceSize					m_imageDstSize;
2185e5c31af7Sopenharmony_ci
2186e5c31af7Sopenharmony_ci	de::MovePtr<BufferWithMemory>	m_buffer;				// result buffer
2187e5c31af7Sopenharmony_ci
2188e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
2189e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>			m_descriptorPool;
2190e5c31af7Sopenharmony_ci	SharedVkDescriptorSet			m_descriptorSet;
2191e5c31af7Sopenharmony_ci
2192e5c31af7Sopenharmony_ci	bool							m_relaxedPrecision;
2193e5c31af7Sopenharmony_ci};
2194e5c31af7Sopenharmony_ci
2195e5c31af7Sopenharmony_ciImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context,
2196e5c31af7Sopenharmony_ci																const Texture& texture,
2197e5c31af7Sopenharmony_ci																const VkFormat readFormat,
2198e5c31af7Sopenharmony_ci																const VkFormat writeFormat,
2199e5c31af7Sopenharmony_ci																bool relaxedPrecision)
2200e5c31af7Sopenharmony_ci	: BaseTestInstance		(context, texture, readFormat, true, true, false, false)
2201e5c31af7Sopenharmony_ci	, m_imageDstFormat		(writeFormat)
2202e5c31af7Sopenharmony_ci	, m_relaxedPrecision	(relaxedPrecision)
2203e5c31af7Sopenharmony_ci{
2204e5c31af7Sopenharmony_ci	const DeviceInterface&		vk				= m_context.getDeviceInterface();
2205e5c31af7Sopenharmony_ci	const VkDevice				device			= m_context.getDevice();
2206e5c31af7Sopenharmony_ci	Allocator&					allocator		= m_context.getDefaultAllocator();
2207e5c31af7Sopenharmony_ci	const deInt32				width			= texture.size().x();
2208e5c31af7Sopenharmony_ci	const deInt32				height			= texture.size().y();
2209e5c31af7Sopenharmony_ci	const tcu::TextureFormat	textureFormat	= mapVkFormat(m_format);
2210e5c31af7Sopenharmony_ci
2211e5c31af7Sopenharmony_ci	// Generate reference image
2212e5c31af7Sopenharmony_ci	m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2213e5c31af7Sopenharmony_ci	m_inputImageData.setStorage(textureFormat, width, height, 1);
2214e5c31af7Sopenharmony_ci
2215e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess	access		= m_inputImageData.getAccess();
2216e5c31af7Sopenharmony_ci	const int						valueStart	= (m_isSigned ? (-width / 2) : 0);
2217e5c31af7Sopenharmony_ci
2218e5c31af7Sopenharmony_ci	for (int x = 0; x < width; ++x)
2219e5c31af7Sopenharmony_ci	for (int y = 0; y < height; ++y)
2220e5c31af7Sopenharmony_ci	{
2221e5c31af7Sopenharmony_ci		const tcu::IVec4 color(valueStart + x, valueStart + y, valueStart, valueStart);
2222e5c31af7Sopenharmony_ci		access.setPixel(color, x, y);
2223e5c31af7Sopenharmony_ci	}
2224e5c31af7Sopenharmony_ci
2225e5c31af7Sopenharmony_ci	// Create source image
2226e5c31af7Sopenharmony_ci	m_imageSrc = de::MovePtr<Image>(new Image(
2227e5c31af7Sopenharmony_ci		vk, device, allocator,
2228e5c31af7Sopenharmony_ci		makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u),
2229e5c31af7Sopenharmony_ci		MemoryRequirement::Any));
2230e5c31af7Sopenharmony_ci
2231e5c31af7Sopenharmony_ci	// Create destination image
2232e5c31af7Sopenharmony_ci	m_imageDst = de::MovePtr<Image>(new Image(
2233e5c31af7Sopenharmony_ci		vk, device, allocator,
2234e5c31af7Sopenharmony_ci		makeImageCreateInfo(m_texture, m_imageDstFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
2235e5c31af7Sopenharmony_ci		MemoryRequirement::Any));
2236e5c31af7Sopenharmony_ci
2237e5c31af7Sopenharmony_ci	// Compute image and buffer sizes
2238e5c31af7Sopenharmony_ci	m_imageSrcSize					= width * height * tcu::getPixelSize(textureFormat);
2239e5c31af7Sopenharmony_ci	m_imageDstSize					= width * height * tcu::getPixelSize(mapVkFormat(m_imageDstFormat));
2240e5c31af7Sopenharmony_ci	VkDeviceSize bufferSizeBytes	= de::max(m_imageSrcSize, m_imageDstSize);
2241e5c31af7Sopenharmony_ci
2242e5c31af7Sopenharmony_ci	// Create helper buffer able to store input data and image write result
2243e5c31af7Sopenharmony_ci	m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
2244e5c31af7Sopenharmony_ci		vk, device, allocator,
2245e5c31af7Sopenharmony_ci		makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
2246e5c31af7Sopenharmony_ci		MemoryRequirement::HostVisible));
2247e5c31af7Sopenharmony_ci
2248e5c31af7Sopenharmony_ci	const Allocation& alloc = m_buffer->getAllocation();
2249e5c31af7Sopenharmony_ci	deMemcpy(alloc.getHostPtr(), m_inputImageData.getAccess().getDataPtr(), static_cast<size_t>(m_imageSrcSize));
2250e5c31af7Sopenharmony_ci	flushAlloc(vk, device, alloc);
2251e5c31af7Sopenharmony_ci}
2252e5c31af7Sopenharmony_ci
2253e5c31af7Sopenharmony_ciVkDescriptorSetLayout ImageExtendOperandTestInstance::prepareDescriptors (void)
2254e5c31af7Sopenharmony_ci{
2255e5c31af7Sopenharmony_ci	const DeviceInterface&	vk		= m_context.getDeviceInterface();
2256e5c31af7Sopenharmony_ci	const VkDevice			device	= m_context.getDevice();
2257e5c31af7Sopenharmony_ci
2258e5c31af7Sopenharmony_ci	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2259e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2260e5c31af7Sopenharmony_ci		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
2261e5c31af7Sopenharmony_ci		.build(vk, device);
2262e5c31af7Sopenharmony_ci
2263e5c31af7Sopenharmony_ci	m_descriptorPool = DescriptorPoolBuilder()
2264e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2265e5c31af7Sopenharmony_ci		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
2266e5c31af7Sopenharmony_ci		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
2267e5c31af7Sopenharmony_ci
2268e5c31af7Sopenharmony_ci	const VkImageViewType viewType = mapImageViewType(m_texture.type());
2269e5c31af7Sopenharmony_ci	const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2270e5c31af7Sopenharmony_ci
2271e5c31af7Sopenharmony_ci	m_descriptorSet	= makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
2272e5c31af7Sopenharmony_ci	m_imageSrcView	= makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
2273e5c31af7Sopenharmony_ci	m_imageDstView	= makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_imageDstFormat, subresourceRange));
2274e5c31af7Sopenharmony_ci
2275e5c31af7Sopenharmony_ci	return *m_descriptorSetLayout;  // not passing the ownership
2276e5c31af7Sopenharmony_ci}
2277e5c31af7Sopenharmony_ci
2278e5c31af7Sopenharmony_civoid ImageExtendOperandTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
2279e5c31af7Sopenharmony_ci{
2280e5c31af7Sopenharmony_ci	DE_UNREF(layerNdx);
2281e5c31af7Sopenharmony_ci
2282e5c31af7Sopenharmony_ci	const DeviceInterface&	vk				= m_context.getDeviceInterface();
2283e5c31af7Sopenharmony_ci	const VkDevice			device			= m_context.getDevice();
2284e5c31af7Sopenharmony_ci	const VkDescriptorSet	descriptorSet	= **m_descriptorSet;
2285e5c31af7Sopenharmony_ci
2286e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageSrcView, VK_IMAGE_LAYOUT_GENERAL);
2287e5c31af7Sopenharmony_ci	const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, **m_imageDstView, VK_IMAGE_LAYOUT_GENERAL);
2288e5c31af7Sopenharmony_ci
2289e5c31af7Sopenharmony_ci	typedef DescriptorSetUpdateBuilder::Location DSUBL;
2290e5c31af7Sopenharmony_ci	DescriptorSetUpdateBuilder()
2291e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DSUBL::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
2292e5c31af7Sopenharmony_ci		.writeSingle(descriptorSet, DSUBL::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
2293e5c31af7Sopenharmony_ci		.update(vk, device);
2294e5c31af7Sopenharmony_ci	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
2295e5c31af7Sopenharmony_ci}
2296e5c31af7Sopenharmony_ci
2297e5c31af7Sopenharmony_civoid ImageExtendOperandTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
2298e5c31af7Sopenharmony_ci{
2299e5c31af7Sopenharmony_ci	const DeviceInterface& vk = m_context.getDeviceInterface();
2300e5c31af7Sopenharmony_ci
2301e5c31af7Sopenharmony_ci	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
2302e5c31af7Sopenharmony_ci	{
2303e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier preCopyImageBarriers[] =
2304e5c31af7Sopenharmony_ci		{
2305e5c31af7Sopenharmony_ci			makeImageMemoryBarrier(
2306e5c31af7Sopenharmony_ci				0u, VK_ACCESS_TRANSFER_WRITE_BIT,
2307e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2308e5c31af7Sopenharmony_ci				m_imageSrc->get(), fullImageSubresourceRange),
2309e5c31af7Sopenharmony_ci			makeImageMemoryBarrier(
2310e5c31af7Sopenharmony_ci				0u, VK_ACCESS_SHADER_WRITE_BIT,
2311e5c31af7Sopenharmony_ci				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
2312e5c31af7Sopenharmony_ci				m_imageDst->get(), fullImageSubresourceRange)
2313e5c31af7Sopenharmony_ci		};
2314e5c31af7Sopenharmony_ci
2315e5c31af7Sopenharmony_ci		const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
2316e5c31af7Sopenharmony_ci			VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2317e5c31af7Sopenharmony_ci			m_buffer->get(), 0ull, m_imageSrcSize);
2318e5c31af7Sopenharmony_ci
2319e5c31af7Sopenharmony_ci		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2320e5c31af7Sopenharmony_ci			(VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
2321e5c31af7Sopenharmony_ci	}
2322e5c31af7Sopenharmony_ci	{
2323e5c31af7Sopenharmony_ci		const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
2324e5c31af7Sopenharmony_ci			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
2325e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
2326e5c31af7Sopenharmony_ci			m_imageSrc->get(), fullImageSubresourceRange);
2327e5c31af7Sopenharmony_ci
2328e5c31af7Sopenharmony_ci		const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
2329e5c31af7Sopenharmony_ci
2330e5c31af7Sopenharmony_ci		vk.cmdCopyBufferToImage(cmdBuffer, m_buffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
2331e5c31af7Sopenharmony_ci		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierAfterCopy);
2332e5c31af7Sopenharmony_ci	}
2333e5c31af7Sopenharmony_ci}
2334e5c31af7Sopenharmony_ci
2335e5c31af7Sopenharmony_civoid ImageExtendOperandTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
2336e5c31af7Sopenharmony_ci{
2337e5c31af7Sopenharmony_ci	commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
2338e5c31af7Sopenharmony_ci}
2339e5c31af7Sopenharmony_ci
2340e5c31af7Sopenharmony_civoid ImageExtendOperandTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
2341e5c31af7Sopenharmony_ci{
2342e5c31af7Sopenharmony_ci	commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
2343e5c31af7Sopenharmony_ci}
2344e5c31af7Sopenharmony_ci
2345e5c31af7Sopenharmony_ci// Clears the high bits of every pixel in the pixel buffer, leaving only the lowest 16 bits of each component.
2346e5c31af7Sopenharmony_civoid clearHighBits (const tcu::PixelBufferAccess& pixels, int width, int height)
2347e5c31af7Sopenharmony_ci{
2348e5c31af7Sopenharmony_ci	for (int y = 0; y < height; ++y)
2349e5c31af7Sopenharmony_ci	for (int x = 0; x < width; ++x)
2350e5c31af7Sopenharmony_ci	{
2351e5c31af7Sopenharmony_ci		auto color = pixels.getPixelUint(x, y);
2352e5c31af7Sopenharmony_ci		for (int c = 0; c < decltype(color)::SIZE; ++c)
2353e5c31af7Sopenharmony_ci			color[c] &= 0xFFFFull;
2354e5c31af7Sopenharmony_ci		pixels.setPixel(color, x, y);
2355e5c31af7Sopenharmony_ci	}
2356e5c31af7Sopenharmony_ci}
2357e5c31af7Sopenharmony_ci
2358e5c31af7Sopenharmony_citcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
2359e5c31af7Sopenharmony_ci{
2360e5c31af7Sopenharmony_ci	const DeviceInterface&			vk			= m_context.getDeviceInterface();
2361e5c31af7Sopenharmony_ci	const VkDevice					device		= m_context.getDevice();
2362e5c31af7Sopenharmony_ci	const tcu::IVec3				imageSize	= m_texture.size();
2363e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess	inputAccess	= m_inputImageData.getAccess();
2364e5c31af7Sopenharmony_ci	const deInt32					width		= inputAccess.getWidth();
2365e5c31af7Sopenharmony_ci	const deInt32					height		= inputAccess.getHeight();
2366e5c31af7Sopenharmony_ci	tcu::TextureLevel				refImage	(mapVkFormat(m_imageDstFormat), width, height);
2367e5c31af7Sopenharmony_ci	tcu::PixelBufferAccess			refAccess	= refImage.getAccess();
2368e5c31af7Sopenharmony_ci
2369e5c31af7Sopenharmony_ci	for (int x = 0; x < width; ++x)
2370e5c31af7Sopenharmony_ci	for (int y = 0; y < height; ++y)
2371e5c31af7Sopenharmony_ci	{
2372e5c31af7Sopenharmony_ci		tcu::IVec4 color = inputAccess.getPixelInt(x, y);
2373e5c31af7Sopenharmony_ci		refAccess.setPixel(color, x, y);
2374e5c31af7Sopenharmony_ci	}
2375e5c31af7Sopenharmony_ci
2376e5c31af7Sopenharmony_ci	const Allocation& alloc = m_buffer->getAllocation();
2377e5c31af7Sopenharmony_ci	invalidateAlloc(vk, device, alloc);
2378e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
2379e5c31af7Sopenharmony_ci
2380e5c31af7Sopenharmony_ci	if (m_relaxedPrecision)
2381e5c31af7Sopenharmony_ci	{
2382e5c31af7Sopenharmony_ci		// Preserve the lowest 16 bits of the reference and result pixels only.
2383e5c31af7Sopenharmony_ci		clearHighBits(refAccess, width, height);
2384e5c31af7Sopenharmony_ci		clearHighBits(result, width, height);
2385e5c31af7Sopenharmony_ci	}
2386e5c31af7Sopenharmony_ci
2387e5c31af7Sopenharmony_ci	if (tcu::intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT, true/*use64Bits*/))
2388e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Passed");
2389e5c31af7Sopenharmony_ci	else
2390e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Image comparison failed");
2391e5c31af7Sopenharmony_ci}
2392e5c31af7Sopenharmony_ci
2393e5c31af7Sopenharmony_cienum class ExtendTestType
2394e5c31af7Sopenharmony_ci{
2395e5c31af7Sopenharmony_ci	READ				= 0,
2396e5c31af7Sopenharmony_ci	WRITE,
2397e5c31af7Sopenharmony_ci	WRITE_NONTEMPORAL,
2398e5c31af7Sopenharmony_ci};
2399e5c31af7Sopenharmony_ci
2400e5c31af7Sopenharmony_cienum class ExtendOperand
2401e5c31af7Sopenharmony_ci{
2402e5c31af7Sopenharmony_ci	SIGN_EXTEND = 0,
2403e5c31af7Sopenharmony_ci	ZERO_EXTEND = 1
2404e5c31af7Sopenharmony_ci};
2405e5c31af7Sopenharmony_ci
2406e5c31af7Sopenharmony_ciclass ImageExtendOperandTest : public TestCase
2407e5c31af7Sopenharmony_ci{
2408e5c31af7Sopenharmony_cipublic:
2409e5c31af7Sopenharmony_ci							ImageExtendOperandTest	(tcu::TestContext&					testCtx,
2410e5c31af7Sopenharmony_ci													 const std::string&					name,
2411e5c31af7Sopenharmony_ci													 const Texture						texture,
2412e5c31af7Sopenharmony_ci													 const VkFormat						readFormat,
2413e5c31af7Sopenharmony_ci													 const VkFormat						writeFormat,
2414e5c31af7Sopenharmony_ci													 const bool							signedInt,
2415e5c31af7Sopenharmony_ci													 const bool							relaxedPrecision,
2416e5c31af7Sopenharmony_ci													 ExtendTestType						extendTestType);
2417e5c31af7Sopenharmony_ci
2418e5c31af7Sopenharmony_ci	void					checkSupport			(Context&				context) const;
2419e5c31af7Sopenharmony_ci	void					initPrograms			(SourceCollections&		programCollection) const;
2420e5c31af7Sopenharmony_ci	TestInstance*			createInstance			(Context&				context) const;
2421e5c31af7Sopenharmony_ci
2422e5c31af7Sopenharmony_ciprivate:
2423e5c31af7Sopenharmony_ci	bool					isWriteTest				() const { return (m_extendTestType == ExtendTestType::WRITE) ||
2424e5c31af7Sopenharmony_ci																	  (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL); }
2425e5c31af7Sopenharmony_ci
2426e5c31af7Sopenharmony_ci	const Texture			m_texture;
2427e5c31af7Sopenharmony_ci	VkFormat				m_readFormat;
2428e5c31af7Sopenharmony_ci	VkFormat				m_writeFormat;
2429e5c31af7Sopenharmony_ci	bool					m_operandForce;			// Use an operand that doesn't match SampledType?
2430e5c31af7Sopenharmony_ci	bool					m_relaxedPrecision;
2431e5c31af7Sopenharmony_ci	ExtendTestType			m_extendTestType;
2432e5c31af7Sopenharmony_ci};
2433e5c31af7Sopenharmony_ci
2434e5c31af7Sopenharmony_ciImageExtendOperandTest::ImageExtendOperandTest (tcu::TestContext&				testCtx,
2435e5c31af7Sopenharmony_ci												const std::string&				name,
2436e5c31af7Sopenharmony_ci												const Texture					texture,
2437e5c31af7Sopenharmony_ci												const VkFormat					readFormat,
2438e5c31af7Sopenharmony_ci												const VkFormat					writeFormat,
2439e5c31af7Sopenharmony_ci												const bool						operandForce,
2440e5c31af7Sopenharmony_ci												const bool						relaxedPrecision,
2441e5c31af7Sopenharmony_ci												ExtendTestType					extendTestType)
2442e5c31af7Sopenharmony_ci	: TestCase						(testCtx, name)
2443e5c31af7Sopenharmony_ci	, m_texture						(texture)
2444e5c31af7Sopenharmony_ci	, m_readFormat					(readFormat)
2445e5c31af7Sopenharmony_ci	, m_writeFormat					(writeFormat)
2446e5c31af7Sopenharmony_ci	, m_operandForce				(operandForce)
2447e5c31af7Sopenharmony_ci	, m_relaxedPrecision			(relaxedPrecision)
2448e5c31af7Sopenharmony_ci	, m_extendTestType				(extendTestType)
2449e5c31af7Sopenharmony_ci{
2450e5c31af7Sopenharmony_ci}
2451e5c31af7Sopenharmony_ci
2452e5c31af7Sopenharmony_civoid checkFormatProperties (const Context& context, VkFormat format)
2453e5c31af7Sopenharmony_ci{
2454e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
2455e5c31af7Sopenharmony_ci	const VkFormatProperties3 formatProperties (context.getFormatProperties(format));
2456e5c31af7Sopenharmony_ci
2457e5c31af7Sopenharmony_ci	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2458e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
2459e5c31af7Sopenharmony_ci#else
2460e5c31af7Sopenharmony_ci	const VkFormatProperties formatProperties(getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), format));
2461e5c31af7Sopenharmony_ci
2462e5c31af7Sopenharmony_ci	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
2463e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Format not supported for storage images");
2464e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
2465e5c31af7Sopenharmony_ci}
2466e5c31af7Sopenharmony_ci
2467e5c31af7Sopenharmony_civoid check64BitSupportIfNeeded (Context& context, VkFormat readFormat, VkFormat writeFormat)
2468e5c31af7Sopenharmony_ci{
2469e5c31af7Sopenharmony_ci	if (is64BitIntegerFormat(readFormat) || is64BitIntegerFormat(writeFormat))
2470e5c31af7Sopenharmony_ci	{
2471e5c31af7Sopenharmony_ci		const auto& features = context.getDeviceFeatures();
2472e5c31af7Sopenharmony_ci		if (!features.shaderInt64)
2473e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "64-bit integers not supported in shaders");
2474e5c31af7Sopenharmony_ci	}
2475e5c31af7Sopenharmony_ci}
2476e5c31af7Sopenharmony_ci
2477e5c31af7Sopenharmony_civoid ImageExtendOperandTest::checkSupport (Context& context) const
2478e5c31af7Sopenharmony_ci{
2479e5c31af7Sopenharmony_ci	if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
2480e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
2481e5c31af7Sopenharmony_ci
2482e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
2483e5c31af7Sopenharmony_ci	DE_ASSERT(m_readFormat != VK_FORMAT_A8_UNORM_KHR && m_writeFormat != VK_FORMAT_A8_UNORM_KHR);
2484e5c31af7Sopenharmony_ci	DE_ASSERT(m_readFormat != VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR && m_writeFormat != VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR);
2485e5c31af7Sopenharmony_ci
2486e5c31af7Sopenharmony_ci	if ((m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL) &&
2487e5c31af7Sopenharmony_ci		(context.getUsedApiVersion() < VK_API_VERSION_1_3))
2488e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Vulkan 1.3 or higher is required for this test to run");
2489e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
2490e5c31af7Sopenharmony_ci
2491e5c31af7Sopenharmony_ci	check64BitSupportIfNeeded(context, m_readFormat, m_writeFormat);
2492e5c31af7Sopenharmony_ci
2493e5c31af7Sopenharmony_ci	checkFormatProperties(context, m_readFormat);
2494e5c31af7Sopenharmony_ci	checkFormatProperties(context, m_writeFormat);
2495e5c31af7Sopenharmony_ci}
2496e5c31af7Sopenharmony_ci
2497e5c31af7Sopenharmony_civoid ImageExtendOperandTest::initPrograms (SourceCollections& programCollection) const
2498e5c31af7Sopenharmony_ci{
2499e5c31af7Sopenharmony_ci	tcu::StringTemplate shaderTemplate(
2500e5c31af7Sopenharmony_ci		"OpCapability Shader\n"
2501e5c31af7Sopenharmony_ci		"OpCapability StorageImageExtendedFormats\n"
2502e5c31af7Sopenharmony_ci
2503e5c31af7Sopenharmony_ci		"${capability}"
2504e5c31af7Sopenharmony_ci		"${extension}"
2505e5c31af7Sopenharmony_ci
2506e5c31af7Sopenharmony_ci		"%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2507e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
2508e5c31af7Sopenharmony_ci		"OpEntryPoint GLCompute %main \"main\" %id %src_image_ptr %dst_image_ptr\n"
2509e5c31af7Sopenharmony_ci		"OpExecutionMode %main LocalSize 1 1 1\n"
2510e5c31af7Sopenharmony_ci
2511e5c31af7Sopenharmony_ci		// decorations
2512e5c31af7Sopenharmony_ci		"OpDecorate %id BuiltIn GlobalInvocationId\n"
2513e5c31af7Sopenharmony_ci
2514e5c31af7Sopenharmony_ci		"OpDecorate %src_image_ptr DescriptorSet 0\n"
2515e5c31af7Sopenharmony_ci		"OpDecorate %src_image_ptr Binding 0\n"
2516e5c31af7Sopenharmony_ci		"OpDecorate %src_image_ptr NonWritable\n"
2517e5c31af7Sopenharmony_ci
2518e5c31af7Sopenharmony_ci		"${relaxed_precision}"
2519e5c31af7Sopenharmony_ci
2520e5c31af7Sopenharmony_ci		"OpDecorate %dst_image_ptr DescriptorSet 0\n"
2521e5c31af7Sopenharmony_ci		"OpDecorate %dst_image_ptr Binding 1\n"
2522e5c31af7Sopenharmony_ci		"OpDecorate %dst_image_ptr NonReadable\n"
2523e5c31af7Sopenharmony_ci
2524e5c31af7Sopenharmony_ci		// types
2525e5c31af7Sopenharmony_ci		"%type_void                          = OpTypeVoid\n"
2526e5c31af7Sopenharmony_ci		"%type_i32                           = OpTypeInt 32 1\n"
2527e5c31af7Sopenharmony_ci		"%type_u32                           = OpTypeInt 32 0\n"
2528e5c31af7Sopenharmony_ci		"%type_vec2_i32                      = OpTypeVector %type_i32 2\n"
2529e5c31af7Sopenharmony_ci		"%type_vec2_u32                      = OpTypeVector %type_u32 2\n"
2530e5c31af7Sopenharmony_ci		"%type_vec3_i32                      = OpTypeVector %type_i32 3\n"
2531e5c31af7Sopenharmony_ci		"%type_vec3_u32                      = OpTypeVector %type_u32 3\n"
2532e5c31af7Sopenharmony_ci		"%type_vec4_i32                      = OpTypeVector %type_i32 4\n"
2533e5c31af7Sopenharmony_ci		"%type_vec4_u32                      = OpTypeVector %type_u32 4\n"
2534e5c31af7Sopenharmony_ci		"${extra_types}"
2535e5c31af7Sopenharmony_ci
2536e5c31af7Sopenharmony_ci		"%type_fun_void                      = OpTypeFunction %type_void\n"
2537e5c31af7Sopenharmony_ci
2538e5c31af7Sopenharmony_ci		"${image_types}"
2539e5c31af7Sopenharmony_ci
2540e5c31af7Sopenharmony_ci		"%type_ptr_in_vec3_u32               = OpTypePointer Input %type_vec3_u32\n"
2541e5c31af7Sopenharmony_ci		"%type_ptr_in_u32                    = OpTypePointer Input %type_u32\n"
2542e5c31af7Sopenharmony_ci
2543e5c31af7Sopenharmony_ci		"${image_uniforms}"
2544e5c31af7Sopenharmony_ci
2545e5c31af7Sopenharmony_ci		// variables
2546e5c31af7Sopenharmony_ci		"%id                                 = OpVariable %type_ptr_in_vec3_u32 Input\n"
2547e5c31af7Sopenharmony_ci
2548e5c31af7Sopenharmony_ci		"${image_variables}"
2549e5c31af7Sopenharmony_ci
2550e5c31af7Sopenharmony_ci		// main function
2551e5c31af7Sopenharmony_ci		"%main                               = OpFunction %type_void None %type_fun_void\n"
2552e5c31af7Sopenharmony_ci		"%label                              = OpLabel\n"
2553e5c31af7Sopenharmony_ci
2554e5c31af7Sopenharmony_ci		"${image_load}"
2555e5c31af7Sopenharmony_ci
2556e5c31af7Sopenharmony_ci		"%idvec                              = OpLoad %type_vec3_u32 %id\n"
2557e5c31af7Sopenharmony_ci		"%id_xy                              = OpVectorShuffle %type_vec2_u32 %idvec %idvec 0 1\n"
2558e5c31af7Sopenharmony_ci		"%coord                              = OpBitcast %type_vec2_i32 %id_xy\n"
2559e5c31af7Sopenharmony_ci		"%value                              = OpImageRead ${sampled_type_vec4} %src_image %coord ${read_extend_operand}\n"
2560e5c31af7Sopenharmony_ci		"                                      OpImageWrite %dst_image %coord %value ${write_extend_operand}\n"
2561e5c31af7Sopenharmony_ci		"                                      OpReturn\n"
2562e5c31af7Sopenharmony_ci		"                                      OpFunctionEnd\n");
2563e5c31af7Sopenharmony_ci
2564e5c31af7Sopenharmony_ci	const auto	testedFormat	= mapVkFormat(isWriteTest() ? m_writeFormat : m_readFormat);
2565e5c31af7Sopenharmony_ci	const bool	isSigned		= (getTextureChannelClass(testedFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
2566e5c31af7Sopenharmony_ci
2567e5c31af7Sopenharmony_ci	const auto isRead64		= is64BitIntegerFormat(m_readFormat);
2568e5c31af7Sopenharmony_ci	const auto isWrite64	= is64BitIntegerFormat(m_writeFormat);
2569e5c31af7Sopenharmony_ci	DE_ASSERT(isRead64 == isWrite64);
2570e5c31af7Sopenharmony_ci
2571e5c31af7Sopenharmony_ci	const bool using64Bits				= (isRead64 || isWrite64);
2572e5c31af7Sopenharmony_ci
2573e5c31af7Sopenharmony_ci	// Additional capabilities when needed.
2574e5c31af7Sopenharmony_ci	std::string capability;
2575e5c31af7Sopenharmony_ci	std::string extension;
2576e5c31af7Sopenharmony_ci	std::string extraTypes;
2577e5c31af7Sopenharmony_ci
2578e5c31af7Sopenharmony_ci	if (using64Bits)
2579e5c31af7Sopenharmony_ci	{
2580e5c31af7Sopenharmony_ci			extension  += "OpExtension \"SPV_EXT_shader_image_int64\"\n";
2581e5c31af7Sopenharmony_ci			capability +=
2582e5c31af7Sopenharmony_ci				"OpCapability Int64\n"
2583e5c31af7Sopenharmony_ci				"OpCapability Int64ImageEXT\n"
2584e5c31af7Sopenharmony_ci				;
2585e5c31af7Sopenharmony_ci			extraTypes +=
2586e5c31af7Sopenharmony_ci				"%type_i64                           = OpTypeInt 64 1\n"
2587e5c31af7Sopenharmony_ci				"%type_u64                           = OpTypeInt 64 0\n"
2588e5c31af7Sopenharmony_ci				"%type_vec3_i64                      = OpTypeVector %type_i64 3\n"
2589e5c31af7Sopenharmony_ci				"%type_vec3_u64                      = OpTypeVector %type_u64 3\n"
2590e5c31af7Sopenharmony_ci				"%type_vec4_i64                      = OpTypeVector %type_i64 4\n"
2591e5c31af7Sopenharmony_ci				"%type_vec4_u64                      = OpTypeVector %type_u64 4\n"
2592e5c31af7Sopenharmony_ci				;
2593e5c31af7Sopenharmony_ci	}
2594e5c31af7Sopenharmony_ci
2595e5c31af7Sopenharmony_ci	std::string relaxed = "";
2596e5c31af7Sopenharmony_ci	if (m_relaxedPrecision)
2597e5c31af7Sopenharmony_ci		relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
2598e5c31af7Sopenharmony_ci
2599e5c31af7Sopenharmony_ci	// Sampled type depends on the format sign and mismatch force flag.
2600e5c31af7Sopenharmony_ci	const bool			signedSampleType	= ((isSigned && !m_operandForce) || (!isSigned && m_operandForce));
2601e5c31af7Sopenharmony_ci	const std::string	bits				= (using64Bits ? "64" : "32");
2602e5c31af7Sopenharmony_ci	const std::string	sampledTypePostfix	= (signedSampleType ? "i" : "u") + bits;
2603e5c31af7Sopenharmony_ci	const std::string	extendOperandStr	= (isSigned ? "SignExtend" : "ZeroExtend");
2604e5c31af7Sopenharmony_ci
2605e5c31af7Sopenharmony_ci	std::map<std::string, std::string> specializations
2606e5c31af7Sopenharmony_ci	{
2607e5c31af7Sopenharmony_ci		{ "image_type_id",			"%type_image" },
2608e5c31af7Sopenharmony_ci		{ "image_uni_ptr_type_id",	"%type_ptr_uniform_const_image" },
2609e5c31af7Sopenharmony_ci		{ "image_var_id",			"%src_image_ptr" },
2610e5c31af7Sopenharmony_ci		{ "image_id",				"%src_image" },
2611e5c31af7Sopenharmony_ci		{ "capability",				capability },
2612e5c31af7Sopenharmony_ci		{ "extension",				extension },
2613e5c31af7Sopenharmony_ci		{ "extra_types",			extraTypes },
2614e5c31af7Sopenharmony_ci		{ "relaxed_precision",		relaxed },
2615e5c31af7Sopenharmony_ci		{ "image_format",			getSpirvFormat(m_readFormat) },
2616e5c31af7Sopenharmony_ci		{ "sampled_type",			(std::string("%type_") + sampledTypePostfix) },
2617e5c31af7Sopenharmony_ci		{ "sampled_type_vec4",		(std::string("%type_vec4_") + sampledTypePostfix) },
2618e5c31af7Sopenharmony_ci		{ "read_extend_operand",	(!isWriteTest() ? extendOperandStr : "") },
2619e5c31af7Sopenharmony_ci		{ "write_extend_operand",	(isWriteTest()  ? extendOperandStr : "") },
2620e5c31af7Sopenharmony_ci	};
2621e5c31af7Sopenharmony_ci
2622e5c31af7Sopenharmony_ci	SpirvVersion	spirvVersion	= SPIRV_VERSION_1_4;
2623e5c31af7Sopenharmony_ci	bool			allowSpirv14	= true;
2624e5c31af7Sopenharmony_ci	if (m_extendTestType == ExtendTestType::WRITE_NONTEMPORAL)
2625e5c31af7Sopenharmony_ci	{
2626e5c31af7Sopenharmony_ci		spirvVersion	= SPIRV_VERSION_1_6;
2627e5c31af7Sopenharmony_ci		allowSpirv14	= false;
2628e5c31af7Sopenharmony_ci		specializations["write_extend_operand"] = "Nontemporal";
2629e5c31af7Sopenharmony_ci	}
2630e5c31af7Sopenharmony_ci
2631e5c31af7Sopenharmony_ci	// Addidtional parametrization is needed for a case when source and destination textures have same format
2632e5c31af7Sopenharmony_ci	tcu::StringTemplate imageTypeTemplate(
2633e5c31af7Sopenharmony_ci		"${image_type_id}                     = OpTypeImage ${sampled_type} 2D 0 0 0 2 ${image_format}\n");
2634e5c31af7Sopenharmony_ci	tcu::StringTemplate imageUniformTypeTemplate(
2635e5c31af7Sopenharmony_ci		"${image_uni_ptr_type_id}   = OpTypePointer UniformConstant ${image_type_id}\n");
2636e5c31af7Sopenharmony_ci	tcu::StringTemplate imageVariablesTemplate(
2637e5c31af7Sopenharmony_ci		"${image_var_id}                      = OpVariable ${image_uni_ptr_type_id} UniformConstant\n");
2638e5c31af7Sopenharmony_ci	tcu::StringTemplate imageLoadTemplate(
2639e5c31af7Sopenharmony_ci		"${image_id}                          = OpLoad ${image_type_id} ${image_var_id}\n");
2640e5c31af7Sopenharmony_ci
2641e5c31af7Sopenharmony_ci	std::string imageTypes;
2642e5c31af7Sopenharmony_ci	std::string imageUniformTypes;
2643e5c31af7Sopenharmony_ci	std::string imageVariables;
2644e5c31af7Sopenharmony_ci	std::string imageLoad;
2645e5c31af7Sopenharmony_ci
2646e5c31af7Sopenharmony_ci	// If input image format is the same as output there is less spir-v definitions
2647e5c31af7Sopenharmony_ci	if (m_readFormat == m_writeFormat)
2648e5c31af7Sopenharmony_ci	{
2649e5c31af7Sopenharmony_ci		imageTypes			= imageTypeTemplate.specialize(specializations);
2650e5c31af7Sopenharmony_ci		imageUniformTypes	= imageUniformTypeTemplate.specialize(specializations);
2651e5c31af7Sopenharmony_ci		imageVariables		= imageVariablesTemplate.specialize(specializations);
2652e5c31af7Sopenharmony_ci		imageLoad			= imageLoadTemplate.specialize(specializations);
2653e5c31af7Sopenharmony_ci
2654e5c31af7Sopenharmony_ci		specializations["image_var_id"]				= "%dst_image_ptr";
2655e5c31af7Sopenharmony_ci		specializations["image_id"]					= "%dst_image";
2656e5c31af7Sopenharmony_ci		imageVariables		+= imageVariablesTemplate.specialize(specializations);
2657e5c31af7Sopenharmony_ci		imageLoad			+= imageLoadTemplate.specialize(specializations);
2658e5c31af7Sopenharmony_ci	}
2659e5c31af7Sopenharmony_ci	else
2660e5c31af7Sopenharmony_ci	{
2661e5c31af7Sopenharmony_ci		specializations["image_type_id"]			= "%type_src_image";
2662e5c31af7Sopenharmony_ci		specializations["image_uni_ptr_type_id"]	= "%type_ptr_uniform_const_src_image";
2663e5c31af7Sopenharmony_ci		imageTypes			= imageTypeTemplate.specialize(specializations);
2664e5c31af7Sopenharmony_ci		imageUniformTypes	= imageUniformTypeTemplate.specialize(specializations);
2665e5c31af7Sopenharmony_ci		imageVariables		= imageVariablesTemplate.specialize(specializations);
2666e5c31af7Sopenharmony_ci		imageLoad			= imageLoadTemplate.specialize(specializations);
2667e5c31af7Sopenharmony_ci
2668e5c31af7Sopenharmony_ci		specializations["image_format"]				= getSpirvFormat(m_writeFormat);
2669e5c31af7Sopenharmony_ci		specializations["image_type_id"]			= "%type_dst_image";
2670e5c31af7Sopenharmony_ci		specializations["image_uni_ptr_type_id"]	= "%type_ptr_uniform_const_dst_image";
2671e5c31af7Sopenharmony_ci		specializations["image_var_id"]				= "%dst_image_ptr";
2672e5c31af7Sopenharmony_ci		specializations["image_id"]					= "%dst_image";
2673e5c31af7Sopenharmony_ci		imageTypes			+= imageTypeTemplate.specialize(specializations);
2674e5c31af7Sopenharmony_ci		imageUniformTypes	+= imageUniformTypeTemplate.specialize(specializations);
2675e5c31af7Sopenharmony_ci		imageVariables		+= imageVariablesTemplate.specialize(specializations);
2676e5c31af7Sopenharmony_ci		imageLoad			+= imageLoadTemplate.specialize(specializations);
2677e5c31af7Sopenharmony_ci	}
2678e5c31af7Sopenharmony_ci
2679e5c31af7Sopenharmony_ci	specializations["image_types"]		= imageTypes;
2680e5c31af7Sopenharmony_ci	specializations["image_uniforms"]	= imageUniformTypes;
2681e5c31af7Sopenharmony_ci	specializations["image_variables"]	= imageVariables;
2682e5c31af7Sopenharmony_ci	specializations["image_load"]		= imageLoad;
2683e5c31af7Sopenharmony_ci
2684e5c31af7Sopenharmony_ci	// Specialize whole shader and add it to program collection
2685e5c31af7Sopenharmony_ci	programCollection.spirvAsmSources.add("comp") << shaderTemplate.specialize(specializations)
2686e5c31af7Sopenharmony_ci		<< vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion, allowSpirv14);
2687e5c31af7Sopenharmony_ci}
2688e5c31af7Sopenharmony_ci
2689e5c31af7Sopenharmony_ciTestInstance* ImageExtendOperandTest::createInstance(Context& context) const
2690e5c31af7Sopenharmony_ci{
2691e5c31af7Sopenharmony_ci	return new ImageExtendOperandTestInstance(context, m_texture, m_readFormat, m_writeFormat, m_relaxedPrecision);
2692e5c31af7Sopenharmony_ci}
2693e5c31af7Sopenharmony_ci
2694e5c31af7Sopenharmony_cistatic const Texture s_textures[] =
2695e5c31af7Sopenharmony_ci{
2696e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_1D,			tcu::IVec3(64,	1,	1),	1),
2697e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_1D_ARRAY,	tcu::IVec3(64,	1,	1),	8),
2698e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_2D,			tcu::IVec3(64,	64,	1),	1),
2699e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_2D_ARRAY,	tcu::IVec3(64,	64,	1),	8),
2700e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_3D,			tcu::IVec3(64,	64,	8),	1),
2701e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_CUBE,		tcu::IVec3(64,	64,	1),	6),
2702e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_CUBE_ARRAY,	tcu::IVec3(64,	64,	1),	2*6),
2703e5c31af7Sopenharmony_ci	Texture(IMAGE_TYPE_BUFFER,		tcu::IVec3(64,	1,	1),	1),
2704e5c31af7Sopenharmony_ci};
2705e5c31af7Sopenharmony_ci
2706e5c31af7Sopenharmony_ciconst Texture& getTestTexture (const ImageType imageType)
2707e5c31af7Sopenharmony_ci{
2708e5c31af7Sopenharmony_ci	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2709e5c31af7Sopenharmony_ci		if (s_textures[textureNdx].type() == imageType)
2710e5c31af7Sopenharmony_ci			return s_textures[textureNdx];
2711e5c31af7Sopenharmony_ci
2712e5c31af7Sopenharmony_ci	DE_FATAL("Internal error");
2713e5c31af7Sopenharmony_ci	return s_textures[0];
2714e5c31af7Sopenharmony_ci}
2715e5c31af7Sopenharmony_ci
2716e5c31af7Sopenharmony_cistatic const VkFormat s_formats[] =
2717e5c31af7Sopenharmony_ci{
2718e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32A32_SFLOAT,
2719e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16A16_SFLOAT,
2720e5c31af7Sopenharmony_ci	VK_FORMAT_R32_SFLOAT,
2721e5c31af7Sopenharmony_ci
2722e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32A32_UINT,
2723e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16A16_UINT,
2724e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8A8_UINT,
2725e5c31af7Sopenharmony_ci	VK_FORMAT_R32_UINT,
2726e5c31af7Sopenharmony_ci
2727e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32A32_SINT,
2728e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16A16_SINT,
2729e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8A8_SINT,
2730e5c31af7Sopenharmony_ci	VK_FORMAT_R32_SINT,
2731e5c31af7Sopenharmony_ci
2732e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8A8_UNORM,
2733e5c31af7Sopenharmony_ci
2734e5c31af7Sopenharmony_ci	VK_FORMAT_B8G8R8A8_UNORM,
2735e5c31af7Sopenharmony_ci	VK_FORMAT_B8G8R8A8_UINT,
2736e5c31af7Sopenharmony_ci
2737e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8A8_SNORM,
2738e5c31af7Sopenharmony_ci
2739e5c31af7Sopenharmony_ci	VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2740e5c31af7Sopenharmony_ci
2741e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32_SFLOAT,
2742e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16_SFLOAT,
2743e5c31af7Sopenharmony_ci	VK_FORMAT_R16_SFLOAT,
2744e5c31af7Sopenharmony_ci
2745e5c31af7Sopenharmony_ci	VK_FORMAT_A2B10G10R10_UINT_PACK32,
2746e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32_UINT,
2747e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16_UINT,
2748e5c31af7Sopenharmony_ci	VK_FORMAT_R16_UINT,
2749e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8_UINT,
2750e5c31af7Sopenharmony_ci	VK_FORMAT_R8_UINT,
2751e5c31af7Sopenharmony_ci
2752e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32_SINT,
2753e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16_SINT,
2754e5c31af7Sopenharmony_ci	VK_FORMAT_R16_SINT,
2755e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8_SINT,
2756e5c31af7Sopenharmony_ci	VK_FORMAT_R8_SINT,
2757e5c31af7Sopenharmony_ci
2758e5c31af7Sopenharmony_ci	VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2759e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16A16_UNORM,
2760e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16A16_SNORM,
2761e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16_UNORM,
2762e5c31af7Sopenharmony_ci	VK_FORMAT_R16_UNORM,
2763e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8_UNORM,
2764e5c31af7Sopenharmony_ci	VK_FORMAT_R8_UNORM,
2765e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
2766e5c31af7Sopenharmony_ci	VK_FORMAT_A8_UNORM_KHR,
2767e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
2768e5c31af7Sopenharmony_ci
2769e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16_SNORM,
2770e5c31af7Sopenharmony_ci	VK_FORMAT_R16_SNORM,
2771e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8_SNORM,
2772e5c31af7Sopenharmony_ci	VK_FORMAT_R8_SNORM,
2773e5c31af7Sopenharmony_ci
2774e5c31af7Sopenharmony_ci	VK_FORMAT_R10X6_UNORM_PACK16,
2775e5c31af7Sopenharmony_ci	VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
2776e5c31af7Sopenharmony_ci	VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
2777e5c31af7Sopenharmony_ci
2778e5c31af7Sopenharmony_ci	VK_FORMAT_R4G4_UNORM_PACK8,
2779e5c31af7Sopenharmony_ci	VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2780e5c31af7Sopenharmony_ci	VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2781e5c31af7Sopenharmony_ci	VK_FORMAT_R5G6B5_UNORM_PACK16,
2782e5c31af7Sopenharmony_ci	VK_FORMAT_B5G6R5_UNORM_PACK16,
2783e5c31af7Sopenharmony_ci	VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2784e5c31af7Sopenharmony_ci	VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2785e5c31af7Sopenharmony_ci	VK_FORMAT_A1R5G5B5_UNORM_PACK16,
2786e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
2787e5c31af7Sopenharmony_ci	VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
2788e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
2789e5c31af7Sopenharmony_ci
2790e5c31af7Sopenharmony_ci	VK_FORMAT_B8G8R8A8_SNORM,
2791e5c31af7Sopenharmony_ci	VK_FORMAT_B8G8R8A8_SINT,
2792e5c31af7Sopenharmony_ci	VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2793e5c31af7Sopenharmony_ci	VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2794e5c31af7Sopenharmony_ci	VK_FORMAT_A8B8G8R8_UINT_PACK32,
2795e5c31af7Sopenharmony_ci	VK_FORMAT_A8B8G8R8_SINT_PACK32,
2796e5c31af7Sopenharmony_ci	VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2797e5c31af7Sopenharmony_ci	VK_FORMAT_A2R10G10B10_SNORM_PACK32,
2798e5c31af7Sopenharmony_ci	VK_FORMAT_A2R10G10B10_UINT_PACK32,
2799e5c31af7Sopenharmony_ci	VK_FORMAT_A2R10G10B10_SINT_PACK32,
2800e5c31af7Sopenharmony_ci	VK_FORMAT_A2B10G10R10_SNORM_PACK32,
2801e5c31af7Sopenharmony_ci	VK_FORMAT_A2B10G10R10_SINT_PACK32,
2802e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32_UINT,
2803e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32_SINT,
2804e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32_SFLOAT,
2805e5c31af7Sopenharmony_ci	VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2806e5c31af7Sopenharmony_ci
2807e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8_SRGB,
2808e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8_SRGB,
2809e5c31af7Sopenharmony_ci	VK_FORMAT_B8G8R8_SRGB,
2810e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8A8_SRGB,
2811e5c31af7Sopenharmony_ci	VK_FORMAT_B8G8R8A8_SRGB,
2812e5c31af7Sopenharmony_ci	VK_FORMAT_A8B8G8R8_SRGB_PACK32
2813e5c31af7Sopenharmony_ci};
2814e5c31af7Sopenharmony_ci
2815e5c31af7Sopenharmony_cistatic const VkFormat s_formatsThreeComponent[] =
2816e5c31af7Sopenharmony_ci{
2817e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8_UINT,
2818e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8_SINT,
2819e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8_UNORM,
2820e5c31af7Sopenharmony_ci	VK_FORMAT_R8G8B8_SNORM,
2821e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16_UINT,
2822e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16_SINT,
2823e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16_UNORM,
2824e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16_SNORM,
2825e5c31af7Sopenharmony_ci	VK_FORMAT_R16G16B16_SFLOAT,
2826e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32_UINT,
2827e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32_SINT,
2828e5c31af7Sopenharmony_ci	VK_FORMAT_R32G32B32_SFLOAT,
2829e5c31af7Sopenharmony_ci};
2830e5c31af7Sopenharmony_ci
2831e5c31af7Sopenharmony_cistatic const VkImageTiling s_tilings[] = {
2832e5c31af7Sopenharmony_ci    VK_IMAGE_TILING_OPTIMAL,
2833e5c31af7Sopenharmony_ci    VK_IMAGE_TILING_LINEAR,
2834e5c31af7Sopenharmony_ci};
2835e5c31af7Sopenharmony_ci
2836e5c31af7Sopenharmony_ciconst char* tilingSuffix(VkImageTiling tiling) {
2837e5c31af7Sopenharmony_ci    switch (tiling) {
2838e5c31af7Sopenharmony_ci        case VK_IMAGE_TILING_OPTIMAL:
2839e5c31af7Sopenharmony_ci            return "";
2840e5c31af7Sopenharmony_ci        case VK_IMAGE_TILING_LINEAR:
2841e5c31af7Sopenharmony_ci            return "_linear";
2842e5c31af7Sopenharmony_ci        default:
2843e5c31af7Sopenharmony_ci            return "unknown";
2844e5c31af7Sopenharmony_ci    }
2845e5c31af7Sopenharmony_ci}
2846e5c31af7Sopenharmony_ci
2847e5c31af7Sopenharmony_ci} // anonymous ns
2848e5c31af7Sopenharmony_ci
2849e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
2850e5c31af7Sopenharmony_ci{
2851e5c31af7Sopenharmony_ci	// Plain imageStore() cases
2852e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store"));
2853e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
2854e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
2855e5c31af7Sopenharmony_ci
2856e5c31af7Sopenharmony_ci	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2857e5c31af7Sopenharmony_ci	{
2858e5c31af7Sopenharmony_ci		const Texture& texture = s_textures[textureNdx];
2859e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
2860e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
2861e5c31af7Sopenharmony_ci		const bool isLayered = (texture.numLayers() > 1);
2862e5c31af7Sopenharmony_ci
2863e5c31af7Sopenharmony_ci		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2864e5c31af7Sopenharmony_ci		{
2865e5c31af7Sopenharmony_ci			for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
2866e5c31af7Sopenharmony_ci			{
2867e5c31af7Sopenharmony_ci				const bool hasSpirvFmt = hasSpirvFormat(s_formats[formatNdx]);
2868e5c31af7Sopenharmony_ci				const char* suffix = tilingSuffix(s_tilings[tilingNdx]);
2869e5c31af7Sopenharmony_ci
2870e5c31af7Sopenharmony_ci				if (hasSpirvFmt)
2871e5c31af7Sopenharmony_ci				{
2872e5c31af7Sopenharmony_ci					groupWithFormatByImageViewType->addChild( new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + suffix, texture, s_formats[formatNdx], s_tilings[tilingNdx]));
2873e5c31af7Sopenharmony_ci					// Additional tests where the shader uses constant data for imageStore.
2874e5c31af7Sopenharmony_ci					groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_constant" + suffix, texture, s_formats[formatNdx], s_tilings[tilingNdx], StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER | StoreTest::FLAG_STORE_CONSTANT_VALUE));
2875e5c31af7Sopenharmony_ci				}
2876e5c31af7Sopenharmony_ci				groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + suffix, texture, s_formats[formatNdx], s_tilings[tilingNdx], 0));
2877e5c31af7Sopenharmony_ci
2878e5c31af7Sopenharmony_ci				if (isLayered && hasSpirvFmt)
2879e5c31af7Sopenharmony_ci					groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer" + suffix,
2880e5c31af7Sopenharmony_ci																		   texture, s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL,
2881e5c31af7Sopenharmony_ci																		   StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2882e5c31af7Sopenharmony_ci
2883e5c31af7Sopenharmony_ci				if (texture.type() == IMAGE_TYPE_BUFFER)
2884e5c31af7Sopenharmony_ci				{
2885e5c31af7Sopenharmony_ci					if (hasSpirvFmt)
2886e5c31af7Sopenharmony_ci						groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign" + suffix, texture, s_formats[formatNdx], s_tilings[tilingNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
2887e5c31af7Sopenharmony_ci					groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign" + suffix, texture, s_formats[formatNdx], s_tilings[tilingNdx], StoreTest::FLAG_MINALIGN));
2888e5c31af7Sopenharmony_ci				}
2889e5c31af7Sopenharmony_ci			}
2890e5c31af7Sopenharmony_ci		}
2891e5c31af7Sopenharmony_ci
2892e5c31af7Sopenharmony_ci		testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2893e5c31af7Sopenharmony_ci		testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2894e5c31af7Sopenharmony_ci	}
2895e5c31af7Sopenharmony_ci
2896e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithFormat.release());
2897e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithoutFormat.release());
2898e5c31af7Sopenharmony_ci
2899e5c31af7Sopenharmony_ci	return testGroup.release();
2900e5c31af7Sopenharmony_ci}
2901e5c31af7Sopenharmony_ci
2902e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
2903e5c31af7Sopenharmony_ci{
2904e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
2905e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2906e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2907e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithoutAnyFormat(new tcu::TestCaseGroup(testCtx, "without_any_format", "Do not declare a format layout qualifier for read or write images"));
2908e5c31af7Sopenharmony_ci
2909e5c31af7Sopenharmony_ci	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
2910e5c31af7Sopenharmony_ci	{
2911e5c31af7Sopenharmony_ci		const Texture&	texture			= s_textures[textureNdx];
2912e5c31af7Sopenharmony_ci		const auto		imageTypeName	= getImageTypeName(texture.type());
2913e5c31af7Sopenharmony_ci		const bool		isLayered		= (texture.numLayers() > 1);
2914e5c31af7Sopenharmony_ci
2915e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
2916e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
2917e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithoutAnyFormatByImageViewType (new tcu::TestCaseGroup(testCtx, imageTypeName.c_str()));
2918e5c31af7Sopenharmony_ci
2919e5c31af7Sopenharmony_ci		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
2920e5c31af7Sopenharmony_ci		{
2921e5c31af7Sopenharmony_ci			const auto formatShortString	= getFormatShortString(s_formats[formatNdx]);
2922e5c31af7Sopenharmony_ci			const auto hasSpvFormat			= hasSpirvFormat(s_formats[formatNdx]);
2923e5c31af7Sopenharmony_ci
2924e5c31af7Sopenharmony_ci			for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
2925e5c31af7Sopenharmony_ci			{
2926e5c31af7Sopenharmony_ci				const char* suffix = tilingSuffix(s_tilings[tilingNdx]);
2927e5c31af7Sopenharmony_ci
2928e5c31af7Sopenharmony_ci				if (hasSpvFormat)
2929e5c31af7Sopenharmony_ci				{
2930e5c31af7Sopenharmony_ci					groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx]));
2931e5c31af7Sopenharmony_ci					groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2932e5c31af7Sopenharmony_ci				}
2933e5c31af7Sopenharmony_ci				groupWithoutAnyFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], 0u));
2934e5c31af7Sopenharmony_ci
2935e5c31af7Sopenharmony_ci				if (isLayered && hasSpvFormat)
2936e5c31af7Sopenharmony_ci					groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_single_layer" + suffix,
2937e5c31af7Sopenharmony_ci															 texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx],
2938e5c31af7Sopenharmony_ci															 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2939e5c31af7Sopenharmony_ci
2940e5c31af7Sopenharmony_ci				if (texture.type() == IMAGE_TYPE_BUFFER)
2941e5c31af7Sopenharmony_ci				{
2942e5c31af7Sopenharmony_ci					if (hasSpvFormat)
2943e5c31af7Sopenharmony_ci					{
2944e5c31af7Sopenharmony_ci						groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign" + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2945e5c31af7Sopenharmony_ci						groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign_uniform" + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2946e5c31af7Sopenharmony_ci						groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign" + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2947e5c31af7Sopenharmony_ci						groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign_uniform" + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2948e5c31af7Sopenharmony_ci					}
2949e5c31af7Sopenharmony_ci					groupWithoutAnyFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign" + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN));
2950e5c31af7Sopenharmony_ci					groupWithoutAnyFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign_uniform" + suffix, texture, s_formats[formatNdx], s_formats[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER));
2951e5c31af7Sopenharmony_ci				}
2952e5c31af7Sopenharmony_ci			}
2953e5c31af7Sopenharmony_ci		}
2954e5c31af7Sopenharmony_ci
2955e5c31af7Sopenharmony_ci		if (texture.type() == IMAGE_TYPE_BUFFER)
2956e5c31af7Sopenharmony_ci		{
2957e5c31af7Sopenharmony_ci			for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formatsThreeComponent); ++formatNdx)
2958e5c31af7Sopenharmony_ci			{
2959e5c31af7Sopenharmony_ci				const auto formatShortString = getFormatShortString(s_formatsThreeComponent[formatNdx]);
2960e5c31af7Sopenharmony_ci
2961e5c31af7Sopenharmony_ci				for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(s_tilings); tilingNdx++)
2962e5c31af7Sopenharmony_ci				{
2963e5c31af7Sopenharmony_ci					const char* suffix = tilingSuffix(s_tilings[tilingNdx]);
2964e5c31af7Sopenharmony_ci
2965e5c31af7Sopenharmony_ci					groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_uniform" + suffix, texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2966e5c31af7Sopenharmony_ci					groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, formatShortString + "_minalign_uniform" + suffix, texture, s_formatsThreeComponent[formatNdx], s_formatsThreeComponent[formatNdx], s_tilings[tilingNdx], LoadStoreTest::FLAG_MINALIGN | LoadStoreTest::FLAG_UNIFORM_TEXEL_BUFFER | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
2967e5c31af7Sopenharmony_ci				}
2968e5c31af7Sopenharmony_ci			}
2969e5c31af7Sopenharmony_ci		}
2970e5c31af7Sopenharmony_ci
2971e5c31af7Sopenharmony_ci		testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
2972e5c31af7Sopenharmony_ci		testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
2973e5c31af7Sopenharmony_ci		testGroupWithoutAnyFormat->addChild(groupWithoutAnyFormatByImageViewType.release());
2974e5c31af7Sopenharmony_ci	}
2975e5c31af7Sopenharmony_ci
2976e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithFormat.release());
2977e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithoutFormat.release());
2978e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithoutAnyFormat.release());
2979e5c31af7Sopenharmony_ci
2980e5c31af7Sopenharmony_ci	return testGroup.release();
2981e5c31af7Sopenharmony_ci}
2982e5c31af7Sopenharmony_ci
2983e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageLoadStoreLodAMDTests (tcu::TestContext& testCtx)
2984e5c31af7Sopenharmony_ci{
2985e5c31af7Sopenharmony_ci	static const Texture textures[] =
2986e5c31af7Sopenharmony_ci	{
2987e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_1D_ARRAY,	tcu::IVec3(64,	1,	1),	8, 1, 6),
2988e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_1D,			tcu::IVec3(64,	1,	1),	1, 1, 6),
2989e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_2D,			tcu::IVec3(64,	64,	1),	1, 1, 6),
2990e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_2D_ARRAY,	tcu::IVec3(64,	64,	1),	8, 1, 6),
2991e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_3D,			tcu::IVec3(64,	64,	8),	1, 1, 6),
2992e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_CUBE,		tcu::IVec3(64,	64,	1),	6, 1, 6),
2993e5c31af7Sopenharmony_ci		Texture(IMAGE_TYPE_CUBE_ARRAY,	tcu::IVec3(64,	64,	1),	2*6, 1, 6),
2994e5c31af7Sopenharmony_ci	};
2995e5c31af7Sopenharmony_ci
2996e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_lod", "Cases with imageLoad() followed by imageStore()"));
2997e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
2998e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
2999e5c31af7Sopenharmony_ci
3000e5c31af7Sopenharmony_ci	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(textures); ++textureNdx)
3001e5c31af7Sopenharmony_ci	{
3002e5c31af7Sopenharmony_ci		const Texture& texture = textures[textureNdx];
3003e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3004e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3005e5c31af7Sopenharmony_ci		const bool isLayered = (texture.numLayers() > 1);
3006e5c31af7Sopenharmony_ci
3007e5c31af7Sopenharmony_ci		if (texture.type() == IMAGE_TYPE_BUFFER)
3008e5c31af7Sopenharmony_ci			continue;
3009e5c31af7Sopenharmony_ci
3010e5c31af7Sopenharmony_ci		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3011e5c31af7Sopenharmony_ci		{
3012e5c31af7Sopenharmony_ci			// These tests always require a SPIR-V format for the write image, even if the read
3013e5c31af7Sopenharmony_ci			// image is being used without a format.
3014e5c31af7Sopenharmony_ci			if (!hasSpirvFormat(s_formats[formatNdx]))
3015e5c31af7Sopenharmony_ci				continue;
3016e5c31af7Sopenharmony_ci
3017e5c31af7Sopenharmony_ci			groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), texture, s_formats[formatNdx], s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL, (LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES), DE_TRUE));
3018e5c31af7Sopenharmony_ci			groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), texture, s_formats[formatNdx], s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL, LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES, DE_TRUE));
3019e5c31af7Sopenharmony_ci
3020e5c31af7Sopenharmony_ci			if (isLayered)
3021e5c31af7Sopenharmony_ci				groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer",
3022e5c31af7Sopenharmony_ci														 texture, s_formats[formatNdx], s_formats[formatNdx], VK_IMAGE_TILING_OPTIMAL,
3023e5c31af7Sopenharmony_ci														 LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES, DE_TRUE));
3024e5c31af7Sopenharmony_ci		}
3025e5c31af7Sopenharmony_ci
3026e5c31af7Sopenharmony_ci		testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
3027e5c31af7Sopenharmony_ci		testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
3028e5c31af7Sopenharmony_ci	}
3029e5c31af7Sopenharmony_ci
3030e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithFormat.release());
3031e5c31af7Sopenharmony_ci	testGroup->addChild(testGroupWithoutFormat.release());
3032e5c31af7Sopenharmony_ci
3033e5c31af7Sopenharmony_ci	return testGroup.release();
3034e5c31af7Sopenharmony_ci}
3035e5c31af7Sopenharmony_ci
3036e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
3037e5c31af7Sopenharmony_ci{
3038e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret",	"Cases with differing texture and image formats"));
3039e5c31af7Sopenharmony_ci
3040e5c31af7Sopenharmony_ci	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
3041e5c31af7Sopenharmony_ci	{
3042e5c31af7Sopenharmony_ci		const Texture& texture = s_textures[textureNdx];
3043e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str()));
3044e5c31af7Sopenharmony_ci
3045e5c31af7Sopenharmony_ci		for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
3046e5c31af7Sopenharmony_ci		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
3047e5c31af7Sopenharmony_ci		{
3048e5c31af7Sopenharmony_ci			if (!hasSpirvFormat(s_formats[formatNdx]))
3049e5c31af7Sopenharmony_ci				continue;
3050e5c31af7Sopenharmony_ci
3051e5c31af7Sopenharmony_ci			const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
3052e5c31af7Sopenharmony_ci			if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
3053e5c31af7Sopenharmony_ci				groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, texture, s_formats[formatNdx], s_formats[imageFormatNdx], VK_IMAGE_TILING_OPTIMAL));
3054e5c31af7Sopenharmony_ci		}
3055e5c31af7Sopenharmony_ci		testGroup->addChild(groupByImageViewType.release());
3056e5c31af7Sopenharmony_ci	}
3057e5c31af7Sopenharmony_ci
3058e5c31af7Sopenharmony_ci	return testGroup.release();
3059e5c31af7Sopenharmony_ci}
3060e5c31af7Sopenharmony_ci
3061e5c31af7Sopenharmony_cide::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
3062e5c31af7Sopenharmony_ci{
3063e5c31af7Sopenharmony_ci	const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
3064e5c31af7Sopenharmony_ci	const Texture& texture = getTestTexture(imageType);
3065e5c31af7Sopenharmony_ci	return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, texture, format, format, VK_IMAGE_TILING_OPTIMAL, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_READS | LoadStoreTest::FLAG_DECLARE_FORMAT_IN_SHADER_WRITES));
3066e5c31af7Sopenharmony_ci}
3067e5c31af7Sopenharmony_ci
3068e5c31af7Sopenharmony_cinamespace
3069e5c31af7Sopenharmony_ci{
3070e5c31af7Sopenharmony_ci
3071e5c31af7Sopenharmony_cibool relaxedOK(VkFormat format)
3072e5c31af7Sopenharmony_ci{
3073e5c31af7Sopenharmony_ci	tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
3074e5c31af7Sopenharmony_ci	int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
3075e5c31af7Sopenharmony_ci	return maxBitDepth <= 16;
3076e5c31af7Sopenharmony_ci}
3077e5c31af7Sopenharmony_ci
3078e5c31af7Sopenharmony_ci// Get a format used for reading or writing in extension operand tests. These formats allow representing the shader sampled type to
3079e5c31af7Sopenharmony_ci// verify results from read or write operations.
3080e5c31af7Sopenharmony_ciVkFormat getShaderExtensionOperandFormat (bool isSigned, bool is64Bit)
3081e5c31af7Sopenharmony_ci{
3082e5c31af7Sopenharmony_ci	const VkFormat formats[] =
3083e5c31af7Sopenharmony_ci	{
3084e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_UINT,
3085e5c31af7Sopenharmony_ci		VK_FORMAT_R32G32B32A32_SINT,
3086e5c31af7Sopenharmony_ci		VK_FORMAT_R64_UINT,
3087e5c31af7Sopenharmony_ci		VK_FORMAT_R64_SINT,
3088e5c31af7Sopenharmony_ci	};
3089e5c31af7Sopenharmony_ci	return formats[2u * (is64Bit ? 1u : 0u) + (isSigned ? 1u : 0u)];
3090e5c31af7Sopenharmony_ci}
3091e5c31af7Sopenharmony_ci
3092e5c31af7Sopenharmony_ci// INT or UINT format?
3093e5c31af7Sopenharmony_cibool isIntegralFormat (VkFormat format)
3094e5c31af7Sopenharmony_ci{
3095e5c31af7Sopenharmony_ci	return (isIntFormat(format) || isUintFormat(format));
3096e5c31af7Sopenharmony_ci}
3097e5c31af7Sopenharmony_ci
3098e5c31af7Sopenharmony_ci// Return the list of formats used for the extension operand tests (SignExten/ZeroExtend).
3099e5c31af7Sopenharmony_cistd::vector<VkFormat> getExtensionOperandFormatList (void)
3100e5c31af7Sopenharmony_ci{
3101e5c31af7Sopenharmony_ci	std::vector<VkFormat> formatList;
3102e5c31af7Sopenharmony_ci
3103e5c31af7Sopenharmony_ci	for (auto format : s_formats)
3104e5c31af7Sopenharmony_ci	{
3105e5c31af7Sopenharmony_ci		if (isIntegralFormat(format))
3106e5c31af7Sopenharmony_ci			formatList.push_back(format);
3107e5c31af7Sopenharmony_ci	}
3108e5c31af7Sopenharmony_ci
3109e5c31af7Sopenharmony_ci	formatList.push_back(VK_FORMAT_R64_SINT);
3110e5c31af7Sopenharmony_ci	formatList.push_back(VK_FORMAT_R64_UINT);
3111e5c31af7Sopenharmony_ci
3112e5c31af7Sopenharmony_ci	return formatList;
3113e5c31af7Sopenharmony_ci}
3114e5c31af7Sopenharmony_ci
3115e5c31af7Sopenharmony_ci} // anonymous
3116e5c31af7Sopenharmony_ci
3117e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageExtendOperandsTests(tcu::TestContext& testCtx)
3118e5c31af7Sopenharmony_ci{
3119e5c31af7Sopenharmony_ci	using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
3120e5c31af7Sopenharmony_ci
3121e5c31af7Sopenharmony_ci	GroupPtr testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
3122e5c31af7Sopenharmony_ci
3123e5c31af7Sopenharmony_ci	const struct
3124e5c31af7Sopenharmony_ci	{
3125e5c31af7Sopenharmony_ci		ExtendTestType	testType;
3126e5c31af7Sopenharmony_ci		const char*		name;
3127e5c31af7Sopenharmony_ci	} testTypes[] =
3128e5c31af7Sopenharmony_ci	{
3129e5c31af7Sopenharmony_ci		{ ExtendTestType::READ,					"read"	},
3130e5c31af7Sopenharmony_ci		{ ExtendTestType::WRITE,				"write"	},
3131e5c31af7Sopenharmony_ci	};
3132e5c31af7Sopenharmony_ci
3133e5c31af7Sopenharmony_ci	const auto texture		= Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
3134e5c31af7Sopenharmony_ci	const auto formatList	= getExtensionOperandFormatList();
3135e5c31af7Sopenharmony_ci
3136e5c31af7Sopenharmony_ci	for (const auto format : formatList)
3137e5c31af7Sopenharmony_ci	{
3138e5c31af7Sopenharmony_ci		const auto isInt		= isIntFormat(format);
3139e5c31af7Sopenharmony_ci		const auto isUint		= isUintFormat(format);
3140e5c31af7Sopenharmony_ci		const auto use64Bits	= is64BitIntegerFormat(format);
3141e5c31af7Sopenharmony_ci
3142e5c31af7Sopenharmony_ci		DE_ASSERT(isInt || isUint);
3143e5c31af7Sopenharmony_ci
3144e5c31af7Sopenharmony_ci		GroupPtr formatGroup (new tcu::TestCaseGroup(testCtx, getFormatShortString(format).c_str()));
3145e5c31af7Sopenharmony_ci
3146e5c31af7Sopenharmony_ci		for (const auto& testType : testTypes)
3147e5c31af7Sopenharmony_ci		{
3148e5c31af7Sopenharmony_ci			GroupPtr testTypeGroup (new tcu::TestCaseGroup(testCtx, testType.name));
3149e5c31af7Sopenharmony_ci
3150e5c31af7Sopenharmony_ci			for (int match = 0; match < 2; ++match)
3151e5c31af7Sopenharmony_ci			{
3152e5c31af7Sopenharmony_ci				const bool	mismatched		= (match == 1);
3153e5c31af7Sopenharmony_ci				const char*	matchGroupName	= (mismatched ? "mismatched_sign" : "matched_sign");
3154e5c31af7Sopenharmony_ci
3155e5c31af7Sopenharmony_ci				// SPIR-V does not allow this kind of sampled type override.
3156e5c31af7Sopenharmony_ci				if (mismatched && isUint)
3157e5c31af7Sopenharmony_ci					continue;
3158e5c31af7Sopenharmony_ci
3159e5c31af7Sopenharmony_ci				GroupPtr matchGroup (new tcu::TestCaseGroup(testCtx, matchGroupName));
3160e5c31af7Sopenharmony_ci
3161e5c31af7Sopenharmony_ci				for (int prec = 0; prec < 2; prec++)
3162e5c31af7Sopenharmony_ci				{
3163e5c31af7Sopenharmony_ci					const bool relaxedPrecision = (prec != 0);
3164e5c31af7Sopenharmony_ci
3165e5c31af7Sopenharmony_ci					const char* precisionName	= (relaxedPrecision ? "relaxed_precision" : "normal_precision");
3166e5c31af7Sopenharmony_ci					const auto  signedOther		= ((isInt && !mismatched) || (isUint && mismatched));
3167e5c31af7Sopenharmony_ci					const auto	otherFormat		= getShaderExtensionOperandFormat(signedOther, use64Bits);
3168e5c31af7Sopenharmony_ci					const auto  readFormat		= (testType.testType == ExtendTestType::READ ?  format : otherFormat);
3169e5c31af7Sopenharmony_ci					const auto  writeFormat		= (testType.testType == ExtendTestType::WRITE ? format : otherFormat);
3170e5c31af7Sopenharmony_ci
3171e5c31af7Sopenharmony_ci					if (relaxedPrecision && !relaxedOK(readFormat))
3172e5c31af7Sopenharmony_ci						continue;
3173e5c31af7Sopenharmony_ci
3174e5c31af7Sopenharmony_ci					if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
3175e5c31af7Sopenharmony_ci						continue;
3176e5c31af7Sopenharmony_ci
3177e5c31af7Sopenharmony_ci					matchGroup->addChild(new ImageExtendOperandTest(testCtx, precisionName, texture, readFormat, writeFormat, mismatched, relaxedPrecision, testType.testType));
3178e5c31af7Sopenharmony_ci				}
3179e5c31af7Sopenharmony_ci
3180e5c31af7Sopenharmony_ci				testTypeGroup->addChild(matchGroup.release());
3181e5c31af7Sopenharmony_ci			}
3182e5c31af7Sopenharmony_ci
3183e5c31af7Sopenharmony_ci			formatGroup->addChild(testTypeGroup.release());
3184e5c31af7Sopenharmony_ci		}
3185e5c31af7Sopenharmony_ci
3186e5c31af7Sopenharmony_ci		testGroup->addChild(formatGroup.release());
3187e5c31af7Sopenharmony_ci	}
3188e5c31af7Sopenharmony_ci
3189e5c31af7Sopenharmony_ci	return testGroup.release();
3190e5c31af7Sopenharmony_ci}
3191e5c31af7Sopenharmony_ci
3192e5c31af7Sopenharmony_citcu::TestCaseGroup* createImageNontemporalOperandTests(tcu::TestContext& testCtx)
3193e5c31af7Sopenharmony_ci{
3194e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "nontemporal_operand", "Cases with Nontemporal image operand for SPOIR-V 1.6"));
3195e5c31af7Sopenharmony_ci
3196e5c31af7Sopenharmony_ci	const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
3197e5c31af7Sopenharmony_ci
3198e5c31af7Sopenharmony_ci	// using just integer formats for tests so that ImageExtendOperandTest could be reused
3199e5c31af7Sopenharmony_ci	const auto formatList = getExtensionOperandFormatList();
3200e5c31af7Sopenharmony_ci
3201e5c31af7Sopenharmony_ci	for (const auto format : formatList)
3202e5c31af7Sopenharmony_ci	{
3203e5c31af7Sopenharmony_ci		const std::string	caseName	= getFormatShortString(format);
3204e5c31af7Sopenharmony_ci		const auto			readFormat	= format;
3205e5c31af7Sopenharmony_ci		const auto			writeFormat	= getShaderExtensionOperandFormat(isIntFormat(format), is64BitIntegerFormat(format));
3206e5c31af7Sopenharmony_ci
3207e5c31af7Sopenharmony_ci		if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
3208e5c31af7Sopenharmony_ci			continue;
3209e5c31af7Sopenharmony_ci
3210e5c31af7Sopenharmony_ci		// note: just testing OpImageWrite as OpImageRead is tested with addComputeImageSamplerTest
3211e5c31af7Sopenharmony_ci		testGroup->addChild(new ImageExtendOperandTest(testCtx, caseName, texture,
3212e5c31af7Sopenharmony_ci			readFormat, writeFormat, false, false, ExtendTestType::WRITE_NONTEMPORAL));
3213e5c31af7Sopenharmony_ci	}
3214e5c31af7Sopenharmony_ci
3215e5c31af7Sopenharmony_ci	return testGroup.release();
3216e5c31af7Sopenharmony_ci}
3217e5c31af7Sopenharmony_ci
3218e5c31af7Sopenharmony_ci} // image
3219e5c31af7Sopenharmony_ci} // vkt
3220