/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Image size Tests
 *//*--------------------------------------------------------------------*/

#include "vktImageSizeTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktImageTestsUtil.hpp"
#include "vktImageTexture.hpp"

#include "vkDefs.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkPlatform.hpp"
#include "vkPrograms.hpp"
#include "vkMemUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"

#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"

#include <string>

using namespace vk;

namespace vkt
{
namespace image
{
namespace
{

//! Get a texture based on image type and suggested size.
Texture getTexture (const ImageType imageType, const tcu::IVec3& size)
{
	switch (imageType)
	{
		case IMAGE_TYPE_1D:
		case IMAGE_TYPE_BUFFER:
			return Texture(imageType, tcu::IVec3(size.x(), 1, 1), 1);

		case IMAGE_TYPE_1D_ARRAY:
			return Texture(imageType, tcu::IVec3(size.x(), 1, 1), size.y());

		case IMAGE_TYPE_2D:
			return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), 1);

		case IMAGE_TYPE_2D_ARRAY:
			return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), size.z());

		case IMAGE_TYPE_CUBE:
			return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 6);

		case IMAGE_TYPE_CUBE_ARRAY:
			return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 2*6);

		case IMAGE_TYPE_3D:
			return Texture(imageType, size, 1);

		default:
			DE_FATAL("Internal error");
			return Texture(IMAGE_TYPE_LAST, tcu::IVec3(), 0);
	}
}

inline VkImageCreateInfo makeImageCreateInfo (const Texture& texture, const VkFormat format)
{
	const VkImageCreateInfo imageParams =
	{
		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,												// VkStructureType			sType;
		DE_NULL,																			// const void*				pNext;
		(isCube(texture) ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u),	// VkImageCreateFlags		flags;
		mapImageType(texture.type()),														// VkImageType				imageType;
		format,																				// VkFormat					format;
		makeExtent3D(texture.layerSize()),													// VkExtent3D				extent;
		1u,																					// deUint32					mipLevels;
		(deUint32)texture.numLayers(),														// deUint32					arrayLayers;
		VK_SAMPLE_COUNT_1_BIT,																// VkSampleCountFlagBits	samples;
		VK_IMAGE_TILING_OPTIMAL,															// VkImageTiling			tiling;
		VK_IMAGE_USAGE_STORAGE_BIT,															// VkImageUsageFlags		usage;
		VK_SHARING_MODE_EXCLUSIVE,															// VkSharingMode			sharingMode;
		0u,																					// deUint32					queueFamilyIndexCount;
		DE_NULL,																			// const deUint32*			pQueueFamilyIndices;
		VK_IMAGE_LAYOUT_UNDEFINED,															// VkImageLayout			initialLayout;
	};
	return imageParams;
}

//! Interpret the memory as IVec3
inline tcu::IVec3 readIVec3 (const void* const data)
{
	const int* const p = reinterpret_cast<const int*>(data);
	return tcu::IVec3(p[0], p[1], p[2]);
}

tcu::IVec3 getExpectedImageSizeResult (const Texture& texture)
{
	// GLSL imageSize() function returns:
	// z = 0 for cubes
	// z = N for cube arrays, where N is the number of cubes
	// y or z = L where L is the number of layers for other array types (e.g. 1D array, 2D array)
	// z = D where D is the depth of 3d image

	const tcu::IVec3 size = texture.size();
	const int numCubeFaces = 6;

	switch (texture.type())
	{
		case IMAGE_TYPE_1D:
		case IMAGE_TYPE_BUFFER:
			return tcu::IVec3(size.x(), 0, 0);

		case IMAGE_TYPE_1D_ARRAY:
		case IMAGE_TYPE_2D:
		case IMAGE_TYPE_CUBE:
			return tcu::IVec3(size.x(), size.y(), 0);

		case IMAGE_TYPE_2D_ARRAY:
		case IMAGE_TYPE_3D:
			return size;

		case IMAGE_TYPE_CUBE_ARRAY:
			return tcu::IVec3(size.x(), size.y(), size.z() / numCubeFaces);

		default:
			DE_FATAL("Internal error");
			return tcu::IVec3();
	}
}

class SizeTest : public TestCase
{
public:
	enum TestFlags
	{
		FLAG_READONLY_IMAGE		= 1u << 0,
		FLAG_WRITEONLY_IMAGE	= 1u << 1,
	};

						SizeTest			(tcu::TestContext&	testCtx,
											 const std::string&	name,
											 const std::string&	description,
											 const Texture&		texture,
											 const VkFormat		format,
											 const deUint32		flags = 0);

	void				initPrograms		(SourceCollections& programCollection) const;
	TestInstance*		createInstance		(Context&			context) const;

private:
	const Texture		m_texture;
	const VkFormat		m_format;
	const bool			m_useReadonly;
	const bool			m_useWriteonly;
};

SizeTest::SizeTest (tcu::TestContext&		testCtx,
					const std::string&		name,
					const std::string&		description,
					const Texture&			texture,
					const VkFormat			format,
					const deUint32			flags)
	: TestCase			(testCtx, name, description)
	, m_texture			(texture)
	, m_format			(format)
	, m_useReadonly		((flags & FLAG_READONLY_IMAGE) != 0)
	, m_useWriteonly	((flags & FLAG_WRITEONLY_IMAGE) != 0)
{
	// We expect at least one flag to be set.
	DE_ASSERT(m_useReadonly || m_useWriteonly);
}

void SizeTest::initPrograms (SourceCollections& programCollection) const
{
	const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
	const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), m_texture.type());
	const int dimension = m_texture.dimension();

	std::ostringstream accessQualifier;
	if (m_useReadonly)
		accessQualifier << " readonly";
	if (m_useWriteonly)
		accessQualifier << " writeonly";

	std::ostringstream src;
	src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
		<< "\n"
		<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
		<< "layout (binding = 0, " << formatQualifierStr << ")" << accessQualifier.str() << " uniform highp " << imageTypeStr << " u_image;\n"
		<< "layout (binding = 1) writeonly buffer Output {\n"
		<< "    ivec3 size;\n"
		<< "} sb_out;\n"
		<< "\n"
		<< "void main (void)\n"
		<< "{\n"
		<< (dimension == 1 ?
			"    sb_out.size = ivec3(imageSize(u_image), 0, 0);\n"
			: dimension == 2 || m_texture.type() == IMAGE_TYPE_CUBE ?		// cubes return ivec2
			"    sb_out.size = ivec3(imageSize(u_image), 0);\n"
			: dimension == 3 ?												// cube arrays return ivec3
			"    sb_out.size = imageSize(u_image);\n"
			: "")
		<< "}\n";

	programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
}

//! Build a case name, e.g. "readonly_writeonly_32x32"
std::string getCaseName (const Texture& texture, const deUint32 flags)
{
	std::ostringstream str;
	str << ((flags & SizeTest::FLAG_READONLY_IMAGE) != 0 ? "readonly_" : "")
		<< ((flags & SizeTest::FLAG_WRITEONLY_IMAGE) != 0 ? "writeonly_" : "");

	const int numComponents = texture.dimension();
	for (int i = 0; i < numComponents; ++i)
		str << (i == 0 ? "" : "x") << texture.size()[i];

	return str.str();
}

//! Base test instance for image and buffer tests
class SizeTestInstance : public TestInstance
{
public:
									SizeTestInstance			(Context&				context,
																 const Texture&			texture,
																 const VkFormat			format);

	tcu::TestStatus                 iterate						(void);
	void							checkRequirements			(void) const;

	virtual							~SizeTestInstance			(void) {}

protected:
	virtual VkDescriptorSetLayout	prepareDescriptors			(void) = 0;
	virtual VkDescriptorSet         getDescriptorSet			(void) const = 0;
	virtual void					commandBeforeCompute		(const VkCommandBuffer	cmdBuffer) = 0;

	const Texture					m_texture;
	const VkFormat					m_format;
	const VkDeviceSize				m_resultBufferSizeBytes;
	de::MovePtr<Buffer>				m_resultBuffer;				//!< Shader writes the output here.
};

SizeTestInstance::SizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
	: TestInstance				(context)
	, m_texture					(texture)
	, m_format					(format)
	, m_resultBufferSizeBytes	(3 * sizeof(deUint32))	// ivec3 in shader
{
	const DeviceInterface&	vk			= m_context.getDeviceInterface();
	const VkDevice			device		= m_context.getDevice();
	Allocator&				allocator	= m_context.getDefaultAllocator();

	// Create an SSBO for shader output.

	m_resultBuffer = de::MovePtr<Buffer>(new Buffer(
		vk, device, allocator,
		makeBufferCreateInfo(m_resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
		MemoryRequirement::HostVisible));
}

void SizeTestInstance::checkRequirements (void) const
{
	if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY && !m_context.getDeviceFeatures().imageCubeArray)
	{
		TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
	}
}

tcu::TestStatus SizeTestInstance::iterate (void)
{
	const DeviceInterface&	vk					= m_context.getDeviceInterface();
	const VkDevice			device				= m_context.getDevice();
	const VkQueue			queue				= m_context.getUniversalQueue();
	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();

	checkRequirements();

	// Create memory barriers.

	const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
		VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
		m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);

	// Create the pipeline.

	const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));

	const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
	const VkDescriptorSet descriptorSet = getDescriptorSet();

	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
	const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));

	const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));

	beginCommandBuffer(vk, *cmdBuffer);

	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);

	commandBeforeCompute(*cmdBuffer);
	vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
	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);

	endCommandBuffer(vk, *cmdBuffer);

	submitCommandsAndWait(vk, device, queue, *cmdBuffer);

	// Compare the result.

	const Allocation& bufferAlloc = m_resultBuffer->getAllocation();
	invalidateAlloc(vk, device, bufferAlloc);

	const tcu::IVec3 resultSize = readIVec3(bufferAlloc.getHostPtr());
	const tcu::IVec3 expectedSize = getExpectedImageSizeResult(m_texture);

	if (resultSize != expectedSize)
		return tcu::TestStatus::fail("Incorrect imageSize(): expected " + de::toString(expectedSize) + " but got " + de::toString(resultSize));
	else
		return tcu::TestStatus::pass("Passed");
}

class ImageSizeTestInstance : public SizeTestInstance
{
public:
									ImageSizeTestInstance		(Context&				context,
																 const Texture&			texture,
																 const VkFormat			format);

protected:
	VkDescriptorSetLayout			prepareDescriptors			(void);
	void							commandBeforeCompute		(const VkCommandBuffer	cmdBuffer);

	VkDescriptorSet                 getDescriptorSet			(void) const { return *m_descriptorSet; }

	de::MovePtr<Image>				m_image;
	Move<VkImageView>				m_imageView;
	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
	Move<VkDescriptorPool>			m_descriptorPool;
	Move<VkDescriptorSet>			m_descriptorSet;
};

ImageSizeTestInstance::ImageSizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
	: SizeTestInstance	(context, texture, format)
{
	const DeviceInterface&	vk			= m_context.getDeviceInterface();
	const VkDevice			device		= m_context.getDevice();
	Allocator&				allocator	= m_context.getDefaultAllocator();

	// Create an image. Its data be uninitialized, as we're not reading from it.

	m_image = de::MovePtr<Image>(new Image(vk, device, allocator, makeImageCreateInfo(m_texture, m_format), MemoryRequirement::Any));

	const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
	m_imageView = makeImageView(vk, device, m_image->get(), mapImageViewType(m_texture.type()), m_format, subresourceRange);
}

VkDescriptorSetLayout ImageSizeTestInstance::prepareDescriptors (void)
{
	const DeviceInterface&	vk		= m_context.getDeviceInterface();
	const VkDevice			device	= m_context.getDevice();

	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
		.build(vk, device);

	m_descriptorPool = DescriptorPoolBuilder()
		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);

	const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
	const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);

	DescriptorSetUpdateBuilder()
		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
		.update(vk, device);

	return *m_descriptorSetLayout;
}

void ImageSizeTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
{
	const DeviceInterface& vk = m_context.getDeviceInterface();

	const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
	const VkImageMemoryBarrier barrierSetImageLayout = makeImageMemoryBarrier(
		0u, 0u,
		VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
		m_image->get(), subresourceRange);

	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierSetImageLayout);
}

class BufferSizeTestInstance : public SizeTestInstance
{
public:
									BufferSizeTestInstance		(Context&				context,
																 const Texture&			texture,
																 const VkFormat			format);

protected:
	VkDescriptorSetLayout			prepareDescriptors			(void);

	void							commandBeforeCompute		(const VkCommandBuffer) {}
	VkDescriptorSet					getDescriptorSet			(void) const { return *m_descriptorSet; }

	de::MovePtr<Buffer>				m_imageBuffer;
	Move<VkBufferView>				m_bufferView;
	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
	Move<VkDescriptorPool>			m_descriptorPool;
	Move<VkDescriptorSet>			m_descriptorSet;
};

BufferSizeTestInstance::BufferSizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
	: SizeTestInstance	(context, texture, format)
{
	const DeviceInterface&	vk			= m_context.getDeviceInterface();
	const VkDevice			device		= m_context.getDevice();
	Allocator&				allocator	= m_context.getDefaultAllocator();

	// Create a texel storage buffer. Its data be uninitialized, as we're not reading from it.

	const VkDeviceSize imageSizeBytes = getImageSizeBytes(m_texture.size(), m_format);
	m_imageBuffer = de::MovePtr<Buffer>(new Buffer(vk, device, allocator,
		makeBufferCreateInfo(imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), MemoryRequirement::Any));

	m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, imageSizeBytes);
}

VkDescriptorSetLayout BufferSizeTestInstance::prepareDescriptors (void)
{
	const DeviceInterface&	vk		= m_context.getDeviceInterface();
	const VkDevice			device	= m_context.getDevice();

	m_descriptorSetLayout = DescriptorSetLayoutBuilder()
		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
		.build(vk, device);

	m_descriptorPool = DescriptorPoolBuilder()
		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);

	const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);

	DescriptorSetUpdateBuilder()
		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
		.update(vk, device);

	return *m_descriptorSetLayout;
}

TestInstance* SizeTest::createInstance (Context& context) const
{
	if (m_texture.type() == IMAGE_TYPE_BUFFER)
		return new BufferSizeTestInstance(context, m_texture, m_format);
	else
		return new ImageSizeTestInstance(context, m_texture, m_format);
}

static const ImageType s_imageTypes[] =
{
	IMAGE_TYPE_1D,
	IMAGE_TYPE_1D_ARRAY,
	IMAGE_TYPE_2D,
	IMAGE_TYPE_2D_ARRAY,
	IMAGE_TYPE_3D,
	IMAGE_TYPE_CUBE,
	IMAGE_TYPE_CUBE_ARRAY,
	IMAGE_TYPE_BUFFER,
};

//! Base sizes used to generate actual image/buffer sizes in the test.
static const tcu::IVec3 s_baseImageSizes[] =
{
	tcu::IVec3(32, 32, 32),
	tcu::IVec3(12, 34, 56),
	tcu::IVec3(1,   1,  1),
	tcu::IVec3(7,   1,  1),
};

static const deUint32 s_flags[] =
{
	SizeTest::FLAG_READONLY_IMAGE,
	SizeTest::FLAG_WRITEONLY_IMAGE,
	SizeTest::FLAG_READONLY_IMAGE | SizeTest::FLAG_WRITEONLY_IMAGE,
};

} // anonymous ns

tcu::TestCaseGroup* createImageSizeTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_size", "imageSize() cases"));

	const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT;

	for (int imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++imageTypeNdx)
	{
		de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(s_imageTypes[imageTypeNdx]).c_str(), ""));

		for (int flagNdx = 0; flagNdx < DE_LENGTH_OF_ARRAY(s_flags); ++flagNdx)
		for (int imageSizeNdx = 0; imageSizeNdx < DE_LENGTH_OF_ARRAY(s_baseImageSizes); ++imageSizeNdx)
		{
			const Texture texture = getTexture(s_imageTypes[imageTypeNdx], s_baseImageSizes[imageSizeNdx]);
			imageGroup->addChild(new SizeTest(testCtx, getCaseName(texture, s_flags[flagNdx]), "", texture, format, s_flags[flagNdx]));
		}

		testGroup->addChild(imageGroup.release());
	}
	return testGroup.release();
}

} // image
} // vkt
