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