Home | History | Annotate | Download | only in image
      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 "vkBuilderUtil.hpp"
     38 #include "vkQueryUtil.hpp"
     39 #include "vkImageUtil.hpp"
     40 
     41 #include "deUniquePtr.hpp"
     42 #include "deSharedPtr.hpp"
     43 #include "deStringUtil.hpp"
     44 
     45 #include "tcuImageCompare.hpp"
     46 #include "tcuTexture.hpp"
     47 #include "tcuTextureUtil.hpp"
     48 #include "tcuFloat.hpp"
     49 
     50 #include <string>
     51 #include <vector>
     52 
     53 using namespace vk;
     54 
     55 namespace vkt
     56 {
     57 namespace image
     58 {
     59 namespace
     60 {
     61 
     62 inline VkBufferImageCopy makeBufferImageCopy (const Texture& texture)
     63 {
     64 	return image::makeBufferImageCopy(makeExtent3D(texture.layerSize()), texture.numLayers());
     65 }
     66 
     67 tcu::ConstPixelBufferAccess getLayerOrSlice (const Texture& texture, const tcu::ConstPixelBufferAccess access, const int layer)
     68 {
     69 	switch (texture.type())
     70 	{
     71 		case IMAGE_TYPE_1D:
     72 		case IMAGE_TYPE_2D:
     73 		case IMAGE_TYPE_BUFFER:
     74 			// Not layered
     75 			DE_ASSERT(layer == 0);
     76 			return access;
     77 
     78 		case IMAGE_TYPE_1D_ARRAY:
     79 			return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
     80 
     81 		case IMAGE_TYPE_2D_ARRAY:
     82 		case IMAGE_TYPE_CUBE:
     83 		case IMAGE_TYPE_CUBE_ARRAY:
     84 		case IMAGE_TYPE_3D:			// 3d texture is treated as if depth was the layers
     85 			return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
     86 
     87 		default:
     88 			DE_FATAL("Internal test error");
     89 			return tcu::ConstPixelBufferAccess();
     90 	}
     91 }
     92 
     93 //! \return true if all layers match in both pixel buffers
     94 bool comparePixelBuffers (tcu::TestLog&						log,
     95 						  const Texture&					texture,
     96 						  const VkFormat					format,
     97 						  const tcu::ConstPixelBufferAccess	reference,
     98 						  const tcu::ConstPixelBufferAccess	result)
     99 {
    100 	DE_ASSERT(reference.getFormat() == result.getFormat());
    101 	DE_ASSERT(reference.getSize() == result.getSize());
    102 
    103 	const bool intFormat = isIntegerFormat(format);
    104 	const bool is3d = (texture.type() == IMAGE_TYPE_3D);
    105 	const int numLayersOrSlices = (is3d ? texture.size().z() : texture.numLayers());
    106 	const int numCubeFaces = 6;
    107 
    108 	int passedLayers = 0;
    109 	for (int layerNdx = 0; layerNdx < numLayersOrSlices; ++layerNdx)
    110 	{
    111 		const std::string comparisonName = "Comparison" + de::toString(layerNdx);
    112 		const std::string comparisonDesc = "Image Comparison, " +
    113 			(isCube(texture) ? "face " + de::toString(layerNdx % numCubeFaces) + ", cube " + de::toString(layerNdx / numCubeFaces) :
    114 			is3d			 ? "slice " + de::toString(layerNdx) : "layer " + de::toString(layerNdx));
    115 
    116 		const tcu::ConstPixelBufferAccess refLayer = getLayerOrSlice(texture, reference, layerNdx);
    117 		const tcu::ConstPixelBufferAccess resultLayer = getLayerOrSlice(texture, result, layerNdx);
    118 
    119 		bool ok = false;
    120 		if (intFormat)
    121 			ok = tcu::intThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
    122 		else
    123 			ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
    124 
    125 		if (ok)
    126 			++passedLayers;
    127 	}
    128 	return passedLayers == numLayersOrSlices;
    129 }
    130 
    131 //!< Zero out invalid pixels in the image (denormalized, infinite, NaN values)
    132 void replaceBadFloatReinterpretValues (const tcu::PixelBufferAccess access)
    133 {
    134 	DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_FLOATING_POINT);
    135 
    136 	for (int z = 0; z < access.getDepth(); ++z)
    137 	for (int y = 0; y < access.getHeight(); ++y)
    138 	for (int x = 0; x < access.getWidth(); ++x)
    139 	{
    140 		const tcu::Vec4 color(access.getPixel(x, y, z));
    141 		tcu::Vec4 newColor = color;
    142 
    143 		for (int i = 0; i < 4; ++i)
    144 		{
    145 			if (access.getFormat().type == tcu::TextureFormat::HALF_FLOAT)
    146 			{
    147 				const tcu::Float16 f(color[i]);
    148 				if (f.isDenorm() || f.isInf() || f.isNaN())
    149 					newColor[i] = 0.0f;
    150 			}
    151 			else
    152 			{
    153 				const tcu::Float32 f(color[i]);
    154 				if (f.isDenorm() || f.isInf() || f.isNaN())
    155 					newColor[i] = 0.0f;
    156 			}
    157 		}
    158 
    159 		if (newColor != color)
    160 			access.setPixel(newColor, x, y, z);
    161 	}
    162 }
    163 
    164 //!< replace invalid pixels in the image (-128)
    165 void replaceSnormReinterpretValues (const tcu::PixelBufferAccess access)
    166 {
    167 	DE_ASSERT(tcu::getTextureChannelClass(access.getFormat().type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT);
    168 
    169 	for (int z = 0; z < access.getDepth(); ++z)
    170 	for (int y = 0; y < access.getHeight(); ++y)
    171 	for (int x = 0; x < access.getWidth(); ++x)
    172 	{
    173 		const tcu::IVec4 color(access.getPixelInt(x, y, z));
    174 		tcu::IVec4 newColor = color;
    175 
    176 		for (int i = 0; i < 4; ++i)
    177 		{
    178 			const deInt32 oldColor(color[i]);
    179 			if (oldColor == -128) newColor[i] = -127;
    180 		}
    181 
    182 		if (newColor != color)
    183 		access.setPixel(newColor, x, y, z);
    184 	}
    185 }
    186 
    187 tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat, const VkFormat readFormat)
    188 {
    189 	// Generate a reference image data using the storage format
    190 
    191 	tcu::TextureLevel reference(mapVkFormat(imageFormat), imageSize.x(), imageSize.y(), imageSize.z());
    192 	const tcu::PixelBufferAccess access = reference.getAccess();
    193 
    194 	const float storeColorScale = computeStoreColorScale(imageFormat, imageSize);
    195 	const float storeColorBias = computeStoreColorBias(imageFormat);
    196 
    197 	const bool intFormat = isIntegerFormat(imageFormat);
    198 	const int xMax = imageSize.x() - 1;
    199 	const int yMax = imageSize.y() - 1;
    200 
    201 	for (int z = 0; z < imageSize.z(); ++z)
    202 	for (int y = 0; y < imageSize.y(); ++y)
    203 	for (int x = 0; x < imageSize.x(); ++x)
    204 	{
    205 		const tcu::IVec4 color(x^y^z, (xMax - x)^y^z, x^(yMax - y)^z, (xMax - x)^(yMax - y)^z);
    206 
    207 		if (intFormat)
    208 			access.setPixel(color, x, y, z);
    209 		else
    210 			access.setPixel(color.asFloat()*storeColorScale + storeColorBias, x, y, z);
    211 	}
    212 
    213 	// If the image is to be accessed as a float texture, get rid of invalid values
    214 
    215 	if (isFloatFormat(readFormat) && imageFormat != readFormat)
    216 		replaceBadFloatReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
    217 	if (isSnormFormat(readFormat) && imageFormat != readFormat)
    218 		replaceSnormReinterpretValues(tcu::PixelBufferAccess(mapVkFormat(readFormat), imageSize, access.getDataPtr()));
    219 
    220 	return reference;
    221 }
    222 
    223 inline tcu::TextureLevel generateReferenceImage (const tcu::IVec3& imageSize, const VkFormat imageFormat)
    224 {
    225 	return generateReferenceImage(imageSize, imageFormat, imageFormat);
    226 }
    227 
    228 void flipHorizontally (const tcu::PixelBufferAccess access)
    229 {
    230 	const int xMax = access.getWidth() - 1;
    231 	const int halfWidth = access.getWidth() / 2;
    232 
    233 	if (isIntegerFormat(mapTextureFormat(access.getFormat())))
    234 		for (int z = 0; z < access.getDepth(); z++)
    235 		for (int y = 0; y < access.getHeight(); y++)
    236 		for (int x = 0; x < halfWidth; x++)
    237 		{
    238 			const tcu::UVec4 temp = access.getPixelUint(xMax - x, y, z);
    239 			access.setPixel(access.getPixelUint(x, y, z), xMax - x, y, z);
    240 			access.setPixel(temp, x, y, z);
    241 		}
    242 	else
    243 		for (int z = 0; z < access.getDepth(); z++)
    244 		for (int y = 0; y < access.getHeight(); y++)
    245 		for (int x = 0; x < halfWidth; x++)
    246 		{
    247 			const tcu::Vec4 temp = access.getPixel(xMax - x, y, z);
    248 			access.setPixel(access.getPixel(x, y, z), xMax - x, y, z);
    249 			access.setPixel(temp, x, y, z);
    250 		}
    251 }
    252 
    253 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
    254 {
    255 	return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
    256 }
    257 
    258 void commandImageWriteBarrierBetweenShaderInvocations (Context& context, const VkCommandBuffer cmdBuffer, const VkImage image, const Texture& texture)
    259 {
    260 	const DeviceInterface& vk = context.getDeviceInterface();
    261 
    262 	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
    263 	const VkImageMemoryBarrier shaderWriteBarrier = makeImageMemoryBarrier(
    264 		VK_ACCESS_SHADER_WRITE_BIT, 0u,
    265 		VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL,
    266 		image, fullImageSubresourceRange);
    267 
    268 	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);
    269 }
    270 
    271 void commandBufferWriteBarrierBeforeHostRead (Context& context, const VkCommandBuffer cmdBuffer, const VkBuffer buffer, const VkDeviceSize bufferSizeBytes)
    272 {
    273 	const DeviceInterface& vk = context.getDeviceInterface();
    274 
    275 	const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
    276 		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
    277 		buffer, 0ull, bufferSizeBytes);
    278 
    279 	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);
    280 }
    281 
    282 //! Copy all layers of an image to a buffer.
    283 void commandCopyImageToBuffer (Context&					context,
    284 							   const VkCommandBuffer	cmdBuffer,
    285 							   const VkImage			image,
    286 							   const VkBuffer			buffer,
    287 							   const VkDeviceSize		bufferSizeBytes,
    288 							   const Texture&			texture)
    289 {
    290 	const DeviceInterface& vk = context.getDeviceInterface();
    291 
    292 	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, texture.numLayers());
    293 	const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier(
    294 		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
    295 		VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    296 		image, fullImageSubresourceRange);
    297 
    298 	const VkBufferImageCopy copyRegion = makeBufferImageCopy(texture);
    299 
    300 	const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier(
    301 		VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
    302 		buffer, 0ull, bufferSizeBytes);
    303 
    304 	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);
    305 	vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &copyRegion);
    306 	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);
    307 }
    308 
    309 class StoreTest : public TestCase
    310 {
    311 public:
    312 	enum TestFlags
    313 	{
    314 		FLAG_SINGLE_LAYER_BIND				= 0x1,	//!< Run the shader multiple times, each time binding a different layer.
    315 		FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER	= 0x2,	//!< Declare the format of the images in the shader code
    316 	};
    317 
    318 							StoreTest			(tcu::TestContext&	testCtx,
    319 												 const std::string&	name,
    320 												 const std::string&	description,
    321 												 const Texture&		texture,
    322 												 const VkFormat		format,
    323 												 const deUint32		flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
    324 
    325 	void					initPrograms		(SourceCollections& programCollection) const;
    326 
    327 	TestInstance*			createInstance		(Context&			context) const;
    328 
    329 private:
    330 	const Texture			m_texture;
    331 	const VkFormat			m_format;
    332 	const bool				m_declareImageFormatInShader;
    333 	const bool				m_singleLayerBind;
    334 };
    335 
    336 StoreTest::StoreTest (tcu::TestContext&		testCtx,
    337 					  const std::string&	name,
    338 					  const std::string&	description,
    339 					  const Texture&		texture,
    340 					  const VkFormat		format,
    341 					  const deUint32		flags)
    342 	: TestCase						(testCtx, name, description)
    343 	, m_texture						(texture)
    344 	, m_format						(format)
    345 	, m_declareImageFormatInShader	((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
    346 	, m_singleLayerBind				((flags & FLAG_SINGLE_LAYER_BIND) != 0)
    347 {
    348 	if (m_singleLayerBind)
    349 		DE_ASSERT(m_texture.numLayers() > 1);
    350 }
    351 
    352 void StoreTest::initPrograms (SourceCollections& programCollection) const
    353 {
    354 	const float storeColorScale = computeStoreColorScale(m_format, m_texture.size());
    355 	const float storeColorBias = computeStoreColorBias(m_format);
    356 	DE_ASSERT(colorScaleAndBiasAreValid(m_format, storeColorScale, storeColorBias));
    357 
    358 	const std::string xMax = de::toString(m_texture.size().x() - 1);
    359 	const std::string yMax = de::toString(m_texture.size().y() - 1);
    360 	const std::string signednessPrefix = isUintFormat(m_format) ? "u" : isIntFormat(m_format) ? "i" : "";
    361 	const std::string colorBaseExpr = signednessPrefix + "vec4("
    362 		+ "gx^gy^gz, "
    363 		+ "(" + xMax + "-gx)^gy^gz, "
    364 		+ "gx^(" + yMax + "-gy)^gz, "
    365 		+ "(" + xMax + "-gx)^(" + yMax + "-gy)^gz)";
    366 
    367 	const std::string colorExpr = colorBaseExpr + (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
    368 								  + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
    369 
    370 	const int dimension = (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
    371 	const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
    372 
    373 	const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
    374 	const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
    375 	const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
    376 
    377 	for (deUint32 variant = 0; variant <= 1; variant++)
    378 	{
    379 		std::ostringstream src;
    380 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
    381 			<< "\n"
    382 			<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
    383 		if (variant == 0)
    384 			src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
    385 		else
    386 			src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
    387 
    388 		if (m_singleLayerBind)
    389 			src << "layout (binding = 1) readonly uniform Constants {\n"
    390 				<< "    int u_layerNdx;\n"
    391 				<< "};\n";
    392 
    393 		src << "\n"
    394 			<< "void main (void)\n"
    395 			<< "{\n"
    396 			<< "    int gx = int(gl_GlobalInvocationID.x);\n"
    397 			<< "    int gy = int(gl_GlobalInvocationID.y);\n"
    398 			<< "    int gz = " << (m_singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
    399 			<< "    imageStore(u_image, " << texelCoordStr << ", " << colorExpr << ");\n"
    400 			<< "}\n";
    401 
    402 		programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str());
    403 	}
    404 }
    405 
    406 //! Generic test iteration algorithm for image tests
    407 class BaseTestInstance : public TestInstance
    408 {
    409 public:
    410 									BaseTestInstance						(Context&		context,
    411 																			 const Texture&	texture,
    412 																			 const VkFormat	format,
    413 																			 const bool		declareImageFormatInShader,
    414 																			 const bool		singleLayerBind);
    415 
    416 	tcu::TestStatus                 iterate									(void);
    417 
    418 	virtual							~BaseTestInstance						(void) {}
    419 
    420 protected:
    421 	virtual VkDescriptorSetLayout	prepareDescriptors						(void) = 0;
    422 	virtual tcu::TestStatus			verifyResult							(void) = 0;
    423 
    424 	virtual void					commandBeforeCompute					(const VkCommandBuffer	cmdBuffer) = 0;
    425 	virtual void					commandBetweenShaderInvocations			(const VkCommandBuffer	cmdBuffer) = 0;
    426 	virtual void					commandAfterCompute						(const VkCommandBuffer	cmdBuffer) = 0;
    427 
    428 	virtual void					commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
    429 																			 const VkPipelineLayout pipelineLayout,
    430 																			 const int				layerNdx) = 0;
    431 	virtual void					checkRequirements						(void) {};
    432 
    433 	const Texture					m_texture;
    434 	const VkFormat					m_format;
    435 	const bool						m_declareImageFormatInShader;
    436 	const bool						m_singleLayerBind;
    437 };
    438 
    439 BaseTestInstance::BaseTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind)
    440 	: TestInstance					(context)
    441 	, m_texture						(texture)
    442 	, m_format						(format)
    443 	, m_declareImageFormatInShader	(declareImageFormatInShader)
    444 	, m_singleLayerBind				(singleLayerBind)
    445 {
    446 }
    447 
    448 tcu::TestStatus BaseTestInstance::iterate (void)
    449 {
    450 	checkRequirements();
    451 
    452 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
    453 	const VkDevice					device				= m_context.getDevice();
    454 	const VkQueue					queue				= m_context.getUniversalQueue();
    455 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    456 
    457 	const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get(m_declareImageFormatInShader ? "comp" : "comp_fmt_unknown"), 0));
    458 
    459 	const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
    460 	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
    461 	const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
    462 
    463 	const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, queueFamilyIndex));
    464 	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    465 
    466 	beginCommandBuffer(vk, *cmdBuffer);
    467 
    468 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
    469 	commandBeforeCompute(*cmdBuffer);
    470 
    471 	const tcu::IVec3 workSize = (m_singleLayerBind ? m_texture.layerSize() : m_texture.size());
    472 	const int loopNumLayers = (m_singleLayerBind ? m_texture.numLayers() : 1);
    473 	for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
    474 	{
    475 		commandBindDescriptorsForLayer(*cmdBuffer, *pipelineLayout, layerNdx);
    476 
    477 		if (layerNdx > 0)
    478 			commandBetweenShaderInvocations(*cmdBuffer);
    479 
    480 		vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
    481 	}
    482 
    483 	commandAfterCompute(*cmdBuffer);
    484 
    485 	endCommandBuffer(vk, *cmdBuffer);
    486 
    487 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
    488 
    489 	return verifyResult();
    490 }
    491 
    492 //! Base store test implementation
    493 class StoreTestInstance : public BaseTestInstance
    494 {
    495 public:
    496 									StoreTestInstance						(Context&		context,
    497 																			 const Texture&	texture,
    498 																			 const VkFormat	format,
    499 																			 const bool		declareImageFormatInShader,
    500 																			 const bool		singleLayerBind);
    501 
    502 protected:
    503 	tcu::TestStatus					verifyResult							(void);
    504 
    505 	// Add empty implementations for functions that might be not needed
    506 	void							commandBeforeCompute					(const VkCommandBuffer) {}
    507 	void							commandBetweenShaderInvocations			(const VkCommandBuffer) {}
    508 	void							commandAfterCompute						(const VkCommandBuffer) {}
    509 	void							checkRequirements						(void);
    510 
    511 	de::MovePtr<Buffer>				m_imageBuffer;
    512 	const VkDeviceSize				m_imageSizeBytes;
    513 };
    514 
    515 StoreTestInstance::StoreTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool declareImageFormatInShader, const bool singleLayerBind)
    516 	: BaseTestInstance		(context, texture, format, declareImageFormatInShader, singleLayerBind)
    517 	, m_imageSizeBytes		(getImageSizeBytes(texture.size(), format))
    518 {
    519 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
    520 	const VkDevice			device		= m_context.getDevice();
    521 	Allocator&				allocator	= m_context.getDefaultAllocator();
    522 
    523 	// A helper buffer with enough space to hold the whole image. Usage flags accommodate all derived test instances.
    524 
    525 	m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
    526 		vk, device, allocator,
    527 		makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
    528 		MemoryRequirement::HostVisible));
    529 }
    530 
    531 tcu::TestStatus StoreTestInstance::verifyResult	(void)
    532 {
    533 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
    534 	const VkDevice			device	= m_context.getDevice();
    535 
    536 	const tcu::IVec3 imageSize = m_texture.size();
    537 	const tcu::TextureLevel reference = generateReferenceImage(imageSize, m_format);
    538 
    539 	const Allocation& alloc = m_imageBuffer->getAllocation();
    540 	invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
    541 	const tcu::ConstPixelBufferAccess result(mapVkFormat(m_format), imageSize, alloc.getHostPtr());
    542 
    543 	if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_format, reference.getAccess(), result))
    544 		return tcu::TestStatus::pass("Passed");
    545 	else
    546 		return tcu::TestStatus::fail("Image comparison failed");
    547 }
    548 
    549 void StoreTestInstance::checkRequirements (void)
    550 {
    551 	const VkPhysicalDeviceFeatures	features	= m_context.getDeviceFeatures();
    552 
    553 	if (!m_declareImageFormatInShader && !features.shaderStorageImageWriteWithoutFormat)
    554 		throw tcu::NotSupportedError("shaderStorageImageWriteWithoutFormat feature not supported");
    555 }
    556 
    557 //! Store test for images
    558 class ImageStoreTestInstance : public StoreTestInstance
    559 {
    560 public:
    561 										ImageStoreTestInstance					(Context&				context,
    562 																				 const Texture&			texture,
    563 																				 const VkFormat			format,
    564 																				 const bool				declareImageFormatInShader,
    565 																				 const bool				singleLayerBind);
    566 
    567 protected:
    568 	VkDescriptorSetLayout				prepareDescriptors						(void);
    569 	void								commandBeforeCompute					(const VkCommandBuffer	cmdBuffer);
    570 	void								commandBetweenShaderInvocations			(const VkCommandBuffer	cmdBuffer);
    571 	void								commandAfterCompute						(const VkCommandBuffer	cmdBuffer);
    572 
    573 	void								commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
    574 																				 const VkPipelineLayout pipelineLayout,
    575 																				 const int				layerNdx);
    576 
    577 	de::MovePtr<Image>					m_image;
    578 	de::MovePtr<Buffer>					m_constantsBuffer;
    579 	const VkDeviceSize					m_constantsBufferChunkSizeBytes;
    580 	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
    581 	Move<VkDescriptorPool>				m_descriptorPool;
    582 	std::vector<SharedVkDescriptorSet>	m_allDescriptorSets;
    583 	std::vector<SharedVkImageView>		m_allImageViews;
    584 };
    585 
    586 ImageStoreTestInstance::ImageStoreTestInstance (Context&		context,
    587 												const Texture&	texture,
    588 												const VkFormat	format,
    589 												const bool		declareImageFormatInShader,
    590 												const bool		singleLayerBind)
    591 	: StoreTestInstance					(context, texture, format, declareImageFormatInShader, singleLayerBind)
    592 	, m_constantsBufferChunkSizeBytes	(getOptimalUniformBufferChunkSize(context.getInstanceInterface(), context.getPhysicalDevice(), sizeof(deUint32)))
    593 	, m_allDescriptorSets				(texture.numLayers())
    594 	, m_allImageViews					(texture.numLayers())
    595 {
    596 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
    597 	const VkDevice			device				= m_context.getDevice();
    598 	Allocator&				allocator			= m_context.getDefaultAllocator();
    599 
    600 	m_image = de::MovePtr<Image>(new Image(
    601 		vk, device, allocator,
    602 		makeImageCreateInfo(m_texture, m_format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
    603 		MemoryRequirement::Any));
    604 
    605 	// This buffer will be used to pass constants to the shader
    606 
    607 	const int numLayers = m_texture.numLayers();
    608 	const VkDeviceSize constantsBufferSizeBytes = numLayers * m_constantsBufferChunkSizeBytes;
    609 	m_constantsBuffer = de::MovePtr<Buffer>(new Buffer(
    610 		vk, device, allocator,
    611 		makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
    612 		MemoryRequirement::HostVisible));
    613 
    614 	{
    615 		const Allocation& alloc = m_constantsBuffer->getAllocation();
    616 		deUint8* const basePtr = static_cast<deUint8*>(alloc.getHostPtr());
    617 
    618 		deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
    619 
    620 		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
    621 		{
    622 			deUint32* valuePtr = reinterpret_cast<deUint32*>(basePtr + layerNdx * m_constantsBufferChunkSizeBytes);
    623 			*valuePtr = static_cast<deUint32>(layerNdx);
    624 		}
    625 
    626 		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
    627 	}
    628 }
    629 
    630 VkDescriptorSetLayout ImageStoreTestInstance::prepareDescriptors (void)
    631 {
    632 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
    633 	const VkDevice			device	= m_context.getDevice();
    634 
    635 	const int numLayers = m_texture.numLayers();
    636 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
    637 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
    638 		.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
    639 		.build(vk, device);
    640 
    641 	m_descriptorPool = DescriptorPoolBuilder()
    642 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
    643 		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
    644 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
    645 
    646 	if (m_singleLayerBind)
    647 	{
    648 		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
    649 		{
    650 			m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
    651 			m_allImageViews[layerNdx]     = makeVkSharedPtr(makeImageView(
    652 												vk, device, m_image->get(), mapImageViewType(getImageTypeForSingleLayer(m_texture.type())), m_format,
    653 												makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
    654 		}
    655 	}
    656 	else // bind all layers at once
    657 	{
    658 		m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
    659 		m_allImageViews[0] = makeVkSharedPtr(makeImageView(
    660 								vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format,
    661 								makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
    662 	}
    663 
    664 	return *m_descriptorSetLayout;  // not passing the ownership
    665 }
    666 
    667 void ImageStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
    668 {
    669 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
    670 	const VkDevice			device	= m_context.getDevice();
    671 
    672 	const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
    673 	const VkImageView imageView = **m_allImageViews[layerNdx];
    674 
    675 	const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
    676 
    677 	// Set the next chunk of the constants buffer. Each chunk begins with layer index that we've set before.
    678 	const VkDescriptorBufferInfo descriptorConstantsBufferInfo = makeDescriptorBufferInfo(
    679 		m_constantsBuffer->get(), layerNdx*m_constantsBufferChunkSizeBytes, m_constantsBufferChunkSizeBytes);
    680 
    681 	DescriptorSetUpdateBuilder()
    682 		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
    683 		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
    684 		.update(vk, device);
    685 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
    686 }
    687 
    688 void ImageStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
    689 {
    690 	const DeviceInterface& vk = m_context.getDeviceInterface();
    691 
    692 	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
    693 	const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
    694 		0u, 0u,
    695 		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
    696 		m_image->get(), fullImageSubresourceRange);
    697 
    698 	const VkDeviceSize constantsBufferSize = m_texture.numLayers() * m_constantsBufferChunkSizeBytes;
    699 	const VkBufferMemoryBarrier writeConstantsBarrier = makeBufferMemoryBarrier(
    700 		VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
    701 		m_constantsBuffer->get(), 0ull, constantsBufferSize);
    702 
    703 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &writeConstantsBarrier, 1, &setImageLayoutBarrier);
    704 }
    705 
    706 void ImageStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
    707 {
    708 	commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_image->get(), m_texture);
    709 }
    710 
    711 void ImageStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
    712 {
    713 	commandCopyImageToBuffer(m_context, cmdBuffer, m_image->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
    714 }
    715 
    716 //! Store test for buffers
    717 class BufferStoreTestInstance : public StoreTestInstance
    718 {
    719 public:
    720 									BufferStoreTestInstance					(Context&				context,
    721 																			 const Texture&			texture,
    722 																			 const VkFormat			format,
    723 																			 const bool				declareImageFormatInShader);
    724 
    725 protected:
    726 	VkDescriptorSetLayout			prepareDescriptors						(void);
    727 	void							commandAfterCompute						(const VkCommandBuffer	cmdBuffer);
    728 
    729 	void							commandBindDescriptorsForLayer			(const VkCommandBuffer	cmdBuffer,
    730 																			 const VkPipelineLayout pipelineLayout,
    731 																			 const int				layerNdx);
    732 
    733 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
    734 	Move<VkDescriptorPool>			m_descriptorPool;
    735 	Move<VkDescriptorSet>			m_descriptorSet;
    736 	Move<VkBufferView>				m_bufferView;
    737 };
    738 
    739 BufferStoreTestInstance::BufferStoreTestInstance (Context&			context,
    740 												  const Texture&	texture,
    741 												  const VkFormat	format,
    742 												  const bool		declareImageFormatInShader)
    743 	: StoreTestInstance(context, texture, format, declareImageFormatInShader, false)
    744 {
    745 }
    746 
    747 VkDescriptorSetLayout BufferStoreTestInstance::prepareDescriptors (void)
    748 {
    749 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
    750 	const VkDevice			device	= m_context.getDevice();
    751 
    752 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
    753 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
    754 		.build(vk, device);
    755 
    756 	m_descriptorPool = DescriptorPoolBuilder()
    757 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
    758 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
    759 
    760 	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
    761 	m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
    762 
    763 	return *m_descriptorSetLayout;  // not passing the ownership
    764 }
    765 
    766 void BufferStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
    767 {
    768 	DE_ASSERT(layerNdx == 0);
    769 	DE_UNREF(layerNdx);
    770 
    771 	const VkDevice			device	= m_context.getDevice();
    772 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
    773 
    774 	DescriptorSetUpdateBuilder()
    775 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
    776 		.update(vk, device);
    777 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
    778 }
    779 
    780 void BufferStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
    781 {
    782 	commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBuffer->get(), m_imageSizeBytes);
    783 }
    784 
    785 class LoadStoreTest : public TestCase
    786 {
    787 public:
    788 	enum TestFlags
    789 	{
    790 		FLAG_SINGLE_LAYER_BIND				= 1 << 0,	//!< Run the shader multiple times, each time binding a different layer.
    791 		FLAG_RESTRICT_IMAGES				= 1 << 1,	//!< If given, images in the shader will be qualified with "restrict".
    792 		FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER	= 1 << 2,	//!< Declare the format of the images in the shader code
    793 	};
    794 
    795 							LoadStoreTest			(tcu::TestContext&		testCtx,
    796 													 const std::string&		name,
    797 													 const std::string&		description,
    798 													 const Texture&			texture,
    799 													 const VkFormat			format,
    800 													 const VkFormat			imageFormat,
    801 													 const deUint32			flags = FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER);
    802 
    803 	void					initPrograms			(SourceCollections&		programCollection) const;
    804 	TestInstance*			createInstance			(Context&				context) const;
    805 
    806 private:
    807 	const Texture			m_texture;
    808 	const VkFormat			m_format;						//!< Format as accessed in the shader
    809 	const VkFormat			m_imageFormat;					//!< Storage format
    810 	const bool				m_declareImageFormatInShader;	//!< Whether the shader will specify the format layout qualifier of the images
    811 	const bool				m_singleLayerBind;
    812 	const bool				m_restrictImages;
    813 };
    814 
    815 LoadStoreTest::LoadStoreTest (tcu::TestContext&		testCtx,
    816 							  const std::string&	name,
    817 							  const std::string&	description,
    818 							  const Texture&		texture,
    819 							  const VkFormat		format,
    820 							  const VkFormat		imageFormat,
    821 							  const deUint32		flags)
    822 	: TestCase						(testCtx, name, description)
    823 	, m_texture						(texture)
    824 	, m_format						(format)
    825 	, m_imageFormat					(imageFormat)
    826 	, m_declareImageFormatInShader	((flags & FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER) != 0)
    827 	, m_singleLayerBind				((flags & FLAG_SINGLE_LAYER_BIND) != 0)
    828 	, m_restrictImages				((flags & FLAG_RESTRICT_IMAGES) != 0)
    829 {
    830 	if (m_singleLayerBind)
    831 		DE_ASSERT(m_texture.numLayers() > 1);
    832 
    833 	DE_ASSERT(formatsAreCompatible(m_format, m_imageFormat));
    834 }
    835 
    836 void LoadStoreTest::initPrograms (SourceCollections& programCollection) const
    837 {
    838 	const int			dimension			= (m_singleLayerBind ? m_texture.layerDimension() : m_texture.dimension());
    839 	const ImageType		usedImageType		= (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
    840 	const std::string	formatQualifierStr	= getShaderImageFormatQualifier(mapVkFormat(m_format));
    841 	const std::string	imageTypeStr		= getShaderImageType(mapVkFormat(m_format), usedImageType);
    842 	const std::string	maybeRestrictStr	= (m_restrictImages ? "restrict " : "");
    843 	const std::string	xMax				= de::toString(m_texture.size().x() - 1);
    844 
    845 	for (deUint32 variant = 0; variant <= 1; variant++)
    846 	{
    847 		std::ostringstream src;
    848 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
    849 			<< "\n";
    850 		if (variant != 0)
    851 		{
    852 			src << "#extension GL_EXT_shader_image_load_formatted : require\n";
    853 		}
    854 		src << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
    855 		if (variant == 0)
    856 			src << "layout (binding = 0, " << formatQualifierStr << ") " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
    857 		else
    858 			src << "layout (binding = 0) " << maybeRestrictStr << "readonly uniform " << imageTypeStr << " u_image0;\n";
    859 		src << "layout (binding = 1, " << formatQualifierStr << ") " << maybeRestrictStr << "writeonly uniform " << imageTypeStr << " u_image1;\n"
    860 			<< "\n"
    861 			<< "void main (void)\n"
    862 			<< "{\n"
    863 			<< (dimension == 1 ?
    864 				"    int pos = int(gl_GlobalInvocationID.x);\n"
    865 				"    imageStore(u_image1, pos, imageLoad(u_image0, " + xMax + "-pos));\n"
    866 				: dimension == 2 ?
    867 				"    ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n"
    868 				"    imageStore(u_image1, pos, imageLoad(u_image0, ivec2(" + xMax + "-pos.x, pos.y)));\n"
    869 				: dimension == 3 ?
    870 				"    ivec3 pos = ivec3(gl_GlobalInvocationID);\n"
    871 				"    imageStore(u_image1, pos, imageLoad(u_image0, ivec3(" + xMax + "-pos.x, pos.y, pos.z)));\n"
    872 				: "")
    873 			<< "}\n";
    874 
    875 		programCollection.glslSources.add(variant == 0 ? "comp" : "comp_fmt_unknown") << glu::ComputeSource(src.str());
    876 	}
    877 }
    878 
    879 //! Load/store test base implementation
    880 class LoadStoreTestInstance : public BaseTestInstance
    881 {
    882 public:
    883 									LoadStoreTestInstance				(Context&			context,
    884 																		 const Texture&		texture,
    885 																		 const VkFormat		format,
    886 																		 const VkFormat		imageFormat,
    887 																		 const bool			declareImageFormatInShader,
    888 																		 const bool			singleLayerBind);
    889 
    890 protected:
    891 	virtual Buffer*					getResultBuffer						(void) const = 0;	//!< Get the buffer that contains the result image
    892 
    893 	tcu::TestStatus					verifyResult						(void);
    894 
    895 	// Add empty implementations for functions that might be not needed
    896 	void							commandBeforeCompute				(const VkCommandBuffer) {}
    897 	void							commandBetweenShaderInvocations		(const VkCommandBuffer) {}
    898 	void							commandAfterCompute					(const VkCommandBuffer) {}
    899 	void							checkRequirements					(void);
    900 
    901 	de::MovePtr<Buffer>				m_imageBuffer;		//!< Source data and helper buffer
    902 	const VkDeviceSize				m_imageSizeBytes;
    903 	const VkFormat					m_imageFormat;		//!< Image format (for storage, may be different than texture format)
    904 	tcu::TextureLevel				m_referenceImage;	//!< Used as input data and later to verify result image
    905 };
    906 
    907 LoadStoreTestInstance::LoadStoreTestInstance (Context&			context,
    908 											  const Texture&	texture,
    909 											  const VkFormat	format,
    910 											  const VkFormat	imageFormat,
    911 											  const bool		declareImageFormatInShader,
    912 											  const bool		singleLayerBind)
    913 	: BaseTestInstance		(context, texture, format, declareImageFormatInShader, singleLayerBind)
    914 	, m_imageSizeBytes		(getImageSizeBytes(texture.size(), format))
    915 	, m_imageFormat			(imageFormat)
    916 	, m_referenceImage		(generateReferenceImage(texture.size(), imageFormat, format))
    917 {
    918 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
    919 	const VkDevice			device		= m_context.getDevice();
    920 	Allocator&				allocator	= m_context.getDefaultAllocator();
    921 
    922 	// A helper buffer with enough space to hold the whole image.
    923 
    924 	m_imageBuffer = de::MovePtr<Buffer>(new Buffer(
    925 		vk, device, allocator,
    926 		makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
    927 		MemoryRequirement::HostVisible));
    928 
    929 	// Copy reference data to buffer for subsequent upload to image.
    930 
    931 	const Allocation& alloc = m_imageBuffer->getAllocation();
    932 	deMemcpy(alloc.getHostPtr(), m_referenceImage.getAccess().getDataPtr(), static_cast<size_t>(m_imageSizeBytes));
    933 	flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
    934 }
    935 
    936 tcu::TestStatus LoadStoreTestInstance::verifyResult	(void)
    937 {
    938 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
    939 	const VkDevice			device	= m_context.getDevice();
    940 
    941 	// Apply the same transformation as done in the shader
    942 	const tcu::PixelBufferAccess reference = m_referenceImage.getAccess();
    943 	flipHorizontally(reference);
    944 
    945 	const Allocation& alloc = getResultBuffer()->getAllocation();
    946 	invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_imageSizeBytes);
    947 	const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageFormat), m_texture.size(), alloc.getHostPtr());
    948 
    949 	if (comparePixelBuffers(m_context.getTestContext().getLog(), m_texture, m_imageFormat, reference, result))
    950 		return tcu::TestStatus::pass("Passed");
    951 	else
    952 		return tcu::TestStatus::fail("Image comparison failed");
    953 }
    954 
    955 void LoadStoreTestInstance::checkRequirements (void)
    956 {
    957 	const VkPhysicalDeviceFeatures	features	= m_context.getDeviceFeatures();
    958 
    959 	if (!m_declareImageFormatInShader && !features.shaderStorageImageReadWithoutFormat)
    960 		throw tcu::NotSupportedError("shaderStorageImageReadWithoutFormat feature not supported");
    961 }
    962 
    963 
    964 //! Load/store test for images
    965 class ImageLoadStoreTestInstance : public LoadStoreTestInstance
    966 {
    967 public:
    968 										ImageLoadStoreTestInstance			(Context&				context,
    969 																			 const Texture&			texture,
    970 																			 const VkFormat			format,
    971 																			 const VkFormat			imageFormat,
    972 																			 const bool				declareImageFormatInShader,
    973 																			 const bool				singleLayerBind);
    974 
    975 protected:
    976 	VkDescriptorSetLayout				prepareDescriptors					(void);
    977 	void								commandBeforeCompute				(const VkCommandBuffer	cmdBuffer);
    978 	void								commandBetweenShaderInvocations		(const VkCommandBuffer	cmdBuffer);
    979 	void								commandAfterCompute					(const VkCommandBuffer	cmdBuffer);
    980 
    981 	void								commandBindDescriptorsForLayer		(const VkCommandBuffer	cmdBuffer,
    982 																			 const VkPipelineLayout pipelineLayout,
    983 																			 const int				layerNdx);
    984 
    985 	Buffer*								getResultBuffer						(void) const { return m_imageBuffer.get(); }
    986 
    987 	de::MovePtr<Image>					m_imageSrc;
    988 	de::MovePtr<Image>					m_imageDst;
    989 	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
    990 	Move<VkDescriptorPool>				m_descriptorPool;
    991 	std::vector<SharedVkDescriptorSet>	m_allDescriptorSets;
    992 	std::vector<SharedVkImageView>		m_allSrcImageViews;
    993 	std::vector<SharedVkImageView>		m_allDstImageViews;
    994 };
    995 
    996 ImageLoadStoreTestInstance::ImageLoadStoreTestInstance (Context&		context,
    997 														const Texture&	texture,
    998 														const VkFormat	format,
    999 														const VkFormat	imageFormat,
   1000 														const bool		declareImageFormatInShader,
   1001 														const bool		singleLayerBind)
   1002 	: LoadStoreTestInstance	(context, texture, format, imageFormat, declareImageFormatInShader, singleLayerBind)
   1003 	, m_allDescriptorSets	(texture.numLayers())
   1004 	, m_allSrcImageViews	(texture.numLayers())
   1005 	, m_allDstImageViews	(texture.numLayers())
   1006 {
   1007 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
   1008 	const VkDevice				device				= m_context.getDevice();
   1009 	Allocator&					allocator			= m_context.getDefaultAllocator();
   1010 	const VkImageCreateFlags	imageFlags			= (m_format == m_imageFormat ? 0u : (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT);
   1011 
   1012 	m_imageSrc = de::MovePtr<Image>(new Image(
   1013 		vk, device, allocator,
   1014 		makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, imageFlags),
   1015 		MemoryRequirement::Any));
   1016 
   1017 	m_imageDst = de::MovePtr<Image>(new Image(
   1018 		vk, device, allocator,
   1019 		makeImageCreateInfo(m_texture, m_imageFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, imageFlags),
   1020 		MemoryRequirement::Any));
   1021 }
   1022 
   1023 VkDescriptorSetLayout ImageLoadStoreTestInstance::prepareDescriptors (void)
   1024 {
   1025 	const VkDevice			device	= m_context.getDevice();
   1026 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
   1027 
   1028 	const int numLayers = m_texture.numLayers();
   1029 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
   1030 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
   1031 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
   1032 		.build(vk, device);
   1033 
   1034 	m_descriptorPool = DescriptorPoolBuilder()
   1035 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
   1036 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
   1037 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers);
   1038 
   1039 	if (m_singleLayerBind)
   1040 	{
   1041 		for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
   1042 		{
   1043 			const VkImageViewType viewType = mapImageViewType(getImageTypeForSingleLayer(m_texture.type()));
   1044 			const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u);
   1045 
   1046 			m_allDescriptorSets[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
   1047 			m_allSrcImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
   1048 			m_allDstImageViews[layerNdx]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
   1049 		}
   1050 	}
   1051 	else // bind all layers at once
   1052 	{
   1053 		const VkImageViewType viewType = mapImageViewType(m_texture.type());
   1054 		const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
   1055 
   1056 		m_allDescriptorSets[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout));
   1057 		m_allSrcImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageSrc->get(), viewType, m_format, subresourceRange));
   1058 		m_allDstImageViews[0]  = makeVkSharedPtr(makeImageView(vk, device, m_imageDst->get(), viewType, m_format, subresourceRange));
   1059 	}
   1060 
   1061 	return *m_descriptorSetLayout;  // not passing the ownership
   1062 }
   1063 
   1064 void ImageLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
   1065 {
   1066 	const VkDevice			device	= m_context.getDevice();
   1067 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
   1068 
   1069 	const VkDescriptorSet descriptorSet = **m_allDescriptorSets[layerNdx];
   1070 	const VkImageView	  srcImageView	= **m_allSrcImageViews[layerNdx];
   1071 	const VkImageView	  dstImageView	= **m_allDstImageViews[layerNdx];
   1072 
   1073 	const VkDescriptorImageInfo descriptorSrcImageInfo = makeDescriptorImageInfo(DE_NULL, srcImageView, VK_IMAGE_LAYOUT_GENERAL);
   1074 	const VkDescriptorImageInfo descriptorDstImageInfo = makeDescriptorImageInfo(DE_NULL, dstImageView, VK_IMAGE_LAYOUT_GENERAL);
   1075 
   1076 	DescriptorSetUpdateBuilder()
   1077 		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorSrcImageInfo)
   1078 		.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImageInfo)
   1079 		.update(vk, device);
   1080 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
   1081 }
   1082 
   1083 void ImageLoadStoreTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
   1084 {
   1085 	const DeviceInterface& vk = m_context.getDeviceInterface();
   1086 
   1087 	const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
   1088 	{
   1089 		const VkImageMemoryBarrier preCopyImageBarriers[] =
   1090 		{
   1091 			makeImageMemoryBarrier(
   1092 				0u, VK_ACCESS_TRANSFER_WRITE_BIT,
   1093 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
   1094 				m_imageSrc->get(), fullImageSubresourceRange),
   1095 			makeImageMemoryBarrier(
   1096 				0u, VK_ACCESS_SHADER_WRITE_BIT,
   1097 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
   1098 				m_imageDst->get(), fullImageSubresourceRange)
   1099 		};
   1100 
   1101 		const VkBufferMemoryBarrier barrierFlushHostWriteBeforeCopy = makeBufferMemoryBarrier(
   1102 			VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
   1103 			m_imageBuffer->get(), 0ull, m_imageSizeBytes);
   1104 
   1105 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
   1106 			(VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &barrierFlushHostWriteBeforeCopy, DE_LENGTH_OF_ARRAY(preCopyImageBarriers), preCopyImageBarriers);
   1107 	}
   1108 	{
   1109 		const VkImageMemoryBarrier barrierAfterCopy = makeImageMemoryBarrier(
   1110 			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
   1111 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
   1112 			m_imageSrc->get(), fullImageSubresourceRange);
   1113 
   1114 		const VkBufferImageCopy copyRegion = makeBufferImageCopy(m_texture);
   1115 
   1116 		vk.cmdCopyBufferToImage(cmdBuffer, m_imageBuffer->get(), m_imageSrc->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
   1117 		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);
   1118 	}
   1119 }
   1120 
   1121 void ImageLoadStoreTestInstance::commandBetweenShaderInvocations (const VkCommandBuffer cmdBuffer)
   1122 {
   1123 	commandImageWriteBarrierBetweenShaderInvocations(m_context, cmdBuffer, m_imageDst->get(), m_texture);
   1124 }
   1125 
   1126 void ImageLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
   1127 {
   1128 	commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_imageBuffer->get(), m_imageSizeBytes, m_texture);
   1129 }
   1130 
   1131 //! Load/store test for buffers
   1132 class BufferLoadStoreTestInstance : public LoadStoreTestInstance
   1133 {
   1134 public:
   1135 									BufferLoadStoreTestInstance		(Context&				context,
   1136 																	 const Texture&			texture,
   1137 																	 const VkFormat			format,
   1138 																	 const VkFormat			imageFormat,
   1139 																	 const bool				declareImageFormatInShader);
   1140 
   1141 protected:
   1142 	VkDescriptorSetLayout			prepareDescriptors				(void);
   1143 	void							commandAfterCompute				(const VkCommandBuffer	cmdBuffer);
   1144 
   1145 	void							commandBindDescriptorsForLayer	(const VkCommandBuffer	cmdBuffer,
   1146 																	 const VkPipelineLayout pipelineLayout,
   1147 																	 const int				layerNdx);
   1148 
   1149 	Buffer*							getResultBuffer					(void) const { return m_imageBufferDst.get(); }
   1150 
   1151 	de::MovePtr<Buffer>				m_imageBufferDst;
   1152 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
   1153 	Move<VkDescriptorPool>			m_descriptorPool;
   1154 	Move<VkDescriptorSet>			m_descriptorSet;
   1155 	Move<VkBufferView>				m_bufferViewSrc;
   1156 	Move<VkBufferView>				m_bufferViewDst;
   1157 };
   1158 
   1159 BufferLoadStoreTestInstance::BufferLoadStoreTestInstance (Context&			context,
   1160 														  const Texture&	texture,
   1161 														  const VkFormat	format,
   1162 														  const VkFormat	imageFormat,
   1163 														  const bool		declareImageFormatInShader)
   1164 	: LoadStoreTestInstance(context, texture, format, imageFormat, declareImageFormatInShader, false)
   1165 {
   1166 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
   1167 	const VkDevice			device		= m_context.getDevice();
   1168 	Allocator&				allocator	= m_context.getDefaultAllocator();
   1169 
   1170 	// Create a destination buffer.
   1171 
   1172 	m_imageBufferDst = de::MovePtr<Buffer>(new Buffer(
   1173 		vk, device, allocator,
   1174 		makeBufferCreateInfo(m_imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
   1175 		MemoryRequirement::HostVisible));
   1176 }
   1177 
   1178 VkDescriptorSetLayout BufferLoadStoreTestInstance::prepareDescriptors (void)
   1179 {
   1180 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
   1181 	const VkDevice			device	= m_context.getDevice();
   1182 
   1183 	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
   1184 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
   1185 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
   1186 		.build(vk, device);
   1187 
   1188 	m_descriptorPool = DescriptorPoolBuilder()
   1189 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
   1190 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
   1191 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
   1192 
   1193 	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
   1194 	m_bufferViewSrc = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, m_imageSizeBytes);
   1195 	m_bufferViewDst = makeBufferView(vk, device, m_imageBufferDst->get(), m_format, 0ull, m_imageSizeBytes);
   1196 
   1197 	return *m_descriptorSetLayout;  // not passing the ownership
   1198 }
   1199 
   1200 void BufferLoadStoreTestInstance::commandBindDescriptorsForLayer (const VkCommandBuffer cmdBuffer, const VkPipelineLayout pipelineLayout, const int layerNdx)
   1201 {
   1202 	DE_ASSERT(layerNdx == 0);
   1203 	DE_UNREF(layerNdx);
   1204 
   1205 	const VkDevice			device	= m_context.getDevice();
   1206 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
   1207 
   1208 	DescriptorSetUpdateBuilder()
   1209 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewSrc.get())
   1210 		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferViewDst.get())
   1211 		.update(vk, device);
   1212 	vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
   1213 }
   1214 
   1215 void BufferLoadStoreTestInstance::commandAfterCompute (const VkCommandBuffer cmdBuffer)
   1216 {
   1217 	commandBufferWriteBarrierBeforeHostRead(m_context, cmdBuffer, m_imageBufferDst->get(), m_imageSizeBytes);
   1218 }
   1219 
   1220 TestInstance* StoreTest::createInstance (Context& context) const
   1221 {
   1222 	if (m_texture.type() == IMAGE_TYPE_BUFFER)
   1223 		return new BufferStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader);
   1224 	else
   1225 		return new ImageStoreTestInstance(context, m_texture, m_format, m_declareImageFormatInShader, m_singleLayerBind);
   1226 }
   1227 
   1228 TestInstance* LoadStoreTest::createInstance (Context& context) const
   1229 {
   1230 	if (m_texture.type() == IMAGE_TYPE_BUFFER)
   1231 		return new BufferLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader);
   1232 	else
   1233 		return new ImageLoadStoreTestInstance(context, m_texture, m_format, m_imageFormat, m_declareImageFormatInShader, m_singleLayerBind);
   1234 }
   1235 
   1236 static const Texture s_textures[] =
   1237 {
   1238 	Texture(IMAGE_TYPE_1D,			tcu::IVec3(64,	1,	1),	1),
   1239 	Texture(IMAGE_TYPE_1D_ARRAY,	tcu::IVec3(64,	1,	1),	8),
   1240 	Texture(IMAGE_TYPE_2D,			tcu::IVec3(64,	64,	1),	1),
   1241 	Texture(IMAGE_TYPE_2D_ARRAY,	tcu::IVec3(64,	64,	1),	8),
   1242 	Texture(IMAGE_TYPE_3D,			tcu::IVec3(64,	64,	8),	1),
   1243 	Texture(IMAGE_TYPE_CUBE,		tcu::IVec3(64,	64,	1),	6),
   1244 	Texture(IMAGE_TYPE_CUBE_ARRAY,	tcu::IVec3(64,	64,	1),	2*6),
   1245 	Texture(IMAGE_TYPE_BUFFER,		tcu::IVec3(64,	1,	1),	1),
   1246 };
   1247 
   1248 const Texture& getTestTexture (const ImageType imageType)
   1249 {
   1250 	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
   1251 		if (s_textures[textureNdx].type() == imageType)
   1252 			return s_textures[textureNdx];
   1253 
   1254 	DE_FATAL("Internal error");
   1255 	return s_textures[0];
   1256 }
   1257 
   1258 static const VkFormat s_formats[] =
   1259 {
   1260 	VK_FORMAT_R32G32B32A32_SFLOAT,
   1261 	VK_FORMAT_R16G16B16A16_SFLOAT,
   1262 	VK_FORMAT_R32_SFLOAT,
   1263 
   1264 	VK_FORMAT_R32G32B32A32_UINT,
   1265 	VK_FORMAT_R16G16B16A16_UINT,
   1266 	VK_FORMAT_R8G8B8A8_UINT,
   1267 	VK_FORMAT_R32_UINT,
   1268 
   1269 	VK_FORMAT_R32G32B32A32_SINT,
   1270 	VK_FORMAT_R16G16B16A16_SINT,
   1271 	VK_FORMAT_R8G8B8A8_SINT,
   1272 	VK_FORMAT_R32_SINT,
   1273 
   1274 	VK_FORMAT_R8G8B8A8_UNORM,
   1275 
   1276 	VK_FORMAT_R8G8B8A8_SNORM,
   1277 };
   1278 
   1279 } // anonymous ns
   1280 
   1281 tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
   1282 {
   1283 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "store", "Plain imageStore() cases"));
   1284 	de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for write images"));
   1285 	de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for write images"));
   1286 
   1287 	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
   1288 	{
   1289 		const Texture& texture = s_textures[textureNdx];
   1290 		de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
   1291 		de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
   1292 		const bool isLayered = (texture.numLayers() > 1);
   1293 
   1294 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
   1295 		{
   1296 			groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
   1297 			groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
   1298 
   1299 			if (isLayered)
   1300 				groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
   1301 														texture, s_formats[formatNdx],
   1302 														StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
   1303 		}
   1304 
   1305 		testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
   1306 		testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
   1307 	}
   1308 
   1309 	testGroup->addChild(testGroupWithFormat.release());
   1310 	testGroup->addChild(testGroupWithoutFormat.release());
   1311 
   1312 	return testGroup.release();
   1313 }
   1314 
   1315 tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
   1316 {
   1317 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store", "Cases with imageLoad() followed by imageStore()"));
   1318 	de::MovePtr<tcu::TestCaseGroup> testGroupWithFormat(new tcu::TestCaseGroup(testCtx, "with_format", "Declare a format layout qualifier for read images"));
   1319 	de::MovePtr<tcu::TestCaseGroup> testGroupWithoutFormat(new tcu::TestCaseGroup(testCtx, "without_format", "Do not declare a format layout qualifier for read images"));
   1320 
   1321 	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
   1322 	{
   1323 		const Texture& texture = s_textures[textureNdx];
   1324 		de::MovePtr<tcu::TestCaseGroup> groupWithFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
   1325 		de::MovePtr<tcu::TestCaseGroup> groupWithoutFormatByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
   1326 		const bool isLayered = (texture.numLayers() > 1);
   1327 
   1328 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
   1329 		{
   1330 			groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
   1331 			groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
   1332 
   1333 			if (isLayered)
   1334 				groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
   1335 														texture, s_formats[formatNdx], s_formats[formatNdx],
   1336 														LoadStoreTest::FLAG_SINGLE_LAYER_BIND | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
   1337 		}
   1338 
   1339 		testGroupWithFormat->addChild(groupWithFormatByImageViewType.release());
   1340 		testGroupWithoutFormat->addChild(groupWithoutFormatByImageViewType.release());
   1341 	}
   1342 
   1343 	testGroup->addChild(testGroupWithFormat.release());
   1344 	testGroup->addChild(testGroupWithoutFormat.release());
   1345 
   1346 	return testGroup.release();
   1347 }
   1348 
   1349 tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx)
   1350 {
   1351 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "format_reinterpret",	"Cases with differing texture and image formats"));
   1352 
   1353 	for (int textureNdx = 0; textureNdx < DE_LENGTH_OF_ARRAY(s_textures); ++textureNdx)
   1354 	{
   1355 		const Texture& texture = s_textures[textureNdx];
   1356 		de::MovePtr<tcu::TestCaseGroup> groupByImageViewType (new tcu::TestCaseGroup(testCtx, getImageTypeName(texture.type()).c_str(), ""));
   1357 
   1358 		for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
   1359 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
   1360 		{
   1361 			const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
   1362 			if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
   1363 				groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
   1364 		}
   1365 		testGroup->addChild(groupByImageViewType.release());
   1366 	}
   1367 
   1368 	return testGroup.release();
   1369 }
   1370 
   1371 de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCtx, const ImageType imageType, const std::string& name)
   1372 {
   1373 	const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
   1374 	const Texture& texture = getTestTexture(imageType);
   1375 	return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
   1376 }
   1377 
   1378 } // image
   1379 } // vkt
   1380