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