/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 The Khronos Group Inc.
 * Copyright (c) 2018 The Khronos Group Inc.
 * Copyright (c) 2018 Google Inc.
 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
 *
 * 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 Protected memory stack tests
 *//*--------------------------------------------------------------------*/

#include "vktProtectedMemStackTests.hpp"

#include "vktProtectedMemContext.hpp"
#include "vktProtectedMemUtils.hpp"
#include "vktProtectedMemImageValidator.hpp"
#include "vktTestCase.hpp"
#include "vktTestGroupUtil.hpp"

#include "vkPrograms.hpp"
#include "vkTypeUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuVector.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuStringTemplate.hpp"

#include "gluTextureTestUtil.hpp"

#include "deRandom.hpp"

namespace vkt
{
namespace ProtectedMem
{

namespace
{

struct Params
{
	deUint32	stackSize;
	deUint32	imageWidth;
	deUint32	imageHeight;

	Params (deUint32	stackSize_)
		: stackSize	(stackSize_)
	{
		// Find suitable image dimensions based on stack memory size
		imageWidth = 1;
		imageHeight = 1;
		bool increaseWidth = true;
		while (imageWidth * imageHeight < stackSize)
		{
			if (increaseWidth)
				imageWidth *= 2;
			else
				imageHeight *= 2;

			increaseWidth = !increaseWidth;
		}
	}
};

deUint32 getSeedValue (const Params& params)
{
	return deInt32Hash(params.stackSize);
}

class StackTestInstance : public ProtectedTestInstance
{
public:
								StackTestInstance	(Context&				ctx,
													 const ImageValidator&	validator,
													 const Params&			params);
	virtual tcu::TestStatus		iterate				(void);

private:
	de::MovePtr<tcu::Texture2D>	createTestTexture2D	(void);
	tcu::TestStatus				validateResult		(vk::VkImage			image,
													 vk::VkImageLayout imageLayout,
													 const tcu::Texture2D&	texture2D,
													 const tcu::Sampler&	refSampler);
	void						calculateRef		(tcu::Texture2D&		texture2D);

	const ImageValidator&		m_validator;
	const Params&				m_params;
};

class StackTestCase : public TestCase
{
public:
								StackTestCase	(tcu::TestContext&		testCtx,
												 const std::string&		name,
												 const std::string&		description,
												 const Params&			params)
									: TestCase		(testCtx, name, description)
									, m_validator	(vk::VK_FORMAT_R8G8B8A8_UNORM)
									, m_params		(params)
								{
								}

	virtual						~StackTestCase	(void) {}
	virtual TestInstance*		createInstance	(Context& ctx) const
								{
									return new StackTestInstance(ctx, m_validator, m_params);
								}
	virtual void				initPrograms	(vk::SourceCollections& programCollection) const;

private:
	ImageValidator				m_validator;
	Params						m_params;
};

void StackTestCase::initPrograms (vk::SourceCollections& programCollection) const
{
	m_validator.initPrograms(programCollection);

	// Test validates handling of protected memory allocated on stack.
	// The test copies protected memory content into temporary variable allocated inside function p.
	// Thus test forces protected content to appear on stack.
	// Function p() returns specified protected memory element from the variable allocated on stack.
	// Function u() returns specified protected memory element from the global variable.
	// Values returned by p() and u() should be same.
	// Test is repeated several times (16) to avoid coincidental matches.
	// In case of any mismatches it is signalized to inherited verifier function by setting 0 in result store image.
	// Each invocation validates particular element (bytes) on stack.
	// Number of invocations matches stack size specified in test parameters.
	std::string comp =
		std::string() +
		"#version 450\n"
		"layout(local_size_x = " + de::toString(m_params.imageWidth) + ", local_size_y = " + de::toString(m_params.imageHeight) + ", local_size_z = 1) in;\n"
		"layout(set = 0, binding = 0, rgba8) writeonly uniform highp image2D u_resultImage;\n"
		"layout(set = 0, binding = 1, rgba8) readonly uniform highp image2D u_srcImage;\n"
		"vec4 protectedData[" + de::toString(m_params.stackSize) + "];\n"
		"\n"
		"vec4 p(int idx)\n"
		"{\n"
		"    vec4 localData[" + de::toString(m_params.stackSize) + "];\n"
		"    for (int i = 0; i < " + de::toString(m_params.stackSize) + "; i++)\n"
		"        localData[i] = protectedData[i];\n"
		"    return localData[idx];\n"
		"}\n"
		"\n"
		"vec4 u(int idx)\n"
		"{\n"
		"    return protectedData[idx];\n"
		"}\n"
		"\n"
		"void main() {\n"
		"    const int n = " + de::toString(m_params.stackSize) + ";\n"
		"    int m = 0;\n"
		"    int w = " + de::toString(m_params.imageWidth) + ";\n"
		"    int gx = int(gl_GlobalInvocationID.x);\n"
		"    int gy = int(gl_GlobalInvocationID.y);\n"
		"    int checked_ndx = gy * w + gx;\n"
		"    vec4 outColor;\n"
		"\n"
		"    for (int j = 0; j < 16; j++)\n"
		"    {\n"
		"        for (int i = 0; i < n; i++)\n"
		"        {\n"
		"            const int idx = (i + j) % n;\n"
		"            protectedData[i] = imageLoad(u_srcImage, ivec2(idx % w, idx / w));\n"
		"        }\n"
		"\n"
		"        vec4 vp = p(checked_ndx);\n"
		"        vec4 vu = u(checked_ndx);\n"
		"        if (any(notEqual(vp,vu)))\n"
		"            m++;\n"
		"    }\n"
		"\n"
		"    if (m <= 0)\n"
		"        outColor = vec4(0.0f);\n"
		"    else\n"
		"        outColor = vec4(1.0f);\n"
		"    imageStore(u_resultImage, ivec2(gx, gy), outColor);\n"
		"}\n";

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

StackTestInstance::StackTestInstance (Context&				ctx,
									  const ImageValidator&	validator,
									  const Params&			params)
	: ProtectedTestInstance	(ctx)
	, m_validator			(validator)
	, m_params				(params)
{
}

de::MovePtr<tcu::Texture2D> StackTestInstance::createTestTexture2D (void)
{
	const tcu::TextureFormat		texFmt		= mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM);
	de::MovePtr<tcu::Texture2D>		texture2D	(new tcu::Texture2D(texFmt, m_params.imageWidth, m_params.imageHeight));

	texture2D->allocLevel(0);

	const tcu::PixelBufferAccess&	level		= texture2D->getLevel(0);

	fillWithUniqueColors(level, getSeedValue(m_params));

	return texture2D;
}

tcu::TestStatus StackTestInstance::iterate (void)
{
	ProtectedContext&						ctx					(m_protectedContext);
	const vk::DeviceInterface&				vk					= ctx.getDeviceInterface();
	const vk::VkDevice						device				= ctx.getDevice();
	const vk::VkQueue						queue				= ctx.getQueue();
	const deUint32							queueFamilyIndex	= ctx.getQueueFamilyIndex();
	const vk::VkPhysicalDeviceProperties	properties			= vk::getPhysicalDeviceProperties(ctx.getInstanceDriver(), ctx.getPhysicalDevice());

	vk::Unique<vk::VkCommandPool>			cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));

	de::MovePtr<tcu::Texture2D>				texture2D			= createTestTexture2D();
	const tcu::Sampler						refSampler			= tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
																			   tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);

	vk::Unique<vk::VkShaderModule>			computeShader		(vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("comp"), 0));

	de::MovePtr<vk::ImageWithMemory>		imageSrc;
	de::MovePtr<vk::ImageWithMemory>		imageDst;
	vk::Move<vk::VkSampler>					sampler;
	vk::Move<vk::VkImageView>				imageViewSrc;
	vk::Move<vk::VkImageView>				imageViewDst;

	vk::Move<vk::VkDescriptorSetLayout>		descriptorSetLayout;
	vk::Move<vk::VkDescriptorPool>			descriptorPool;
	vk::Move<vk::VkDescriptorSet>			descriptorSet;

	// Check the number of invocations supported
	if (properties.limits.maxComputeWorkGroupInvocations < m_params.imageWidth * m_params.imageHeight)
		throw tcu::NotSupportedError("Not enough compute workgroup invocations supported.");

	// Create src and dst images
	{
		vk::VkImageUsageFlags imageUsageFlags = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT	|
												vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT	|
												vk::VK_IMAGE_USAGE_SAMPLED_BIT		|
												vk::VK_IMAGE_USAGE_STORAGE_BIT;

		imageSrc = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
								 m_params.imageWidth, m_params.imageHeight,
								 vk::VK_FORMAT_R8G8B8A8_UNORM,
								 imageUsageFlags);

		imageDst = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
								 m_params.imageWidth, m_params.imageHeight,
								 vk::VK_FORMAT_R8G8B8A8_UNORM,
								 imageUsageFlags);
	}

	// Upload source image
	{
		de::MovePtr<vk::ImageWithMemory>	unprotectedImage	= createImage2D(ctx, PROTECTION_DISABLED, queueFamilyIndex,
																				m_params.imageWidth, m_params.imageHeight,
																				vk::VK_FORMAT_R8G8B8A8_UNORM,
																				vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);

		// Upload data to an unprotected image
		uploadImage(m_protectedContext, **unprotectedImage, *texture2D);

		// Copy unprotected image to protected image
		copyToProtectedImage(m_protectedContext, **unprotectedImage, **imageSrc, vk::VK_IMAGE_LAYOUT_GENERAL, m_params.imageWidth, m_params.imageHeight);
	}

	// Clear dst image
	clearImage(m_protectedContext, **imageDst);

	// Create descriptors
	{
		vk::DescriptorSetLayoutBuilder	layoutBuilder;
		vk::DescriptorPoolBuilder		poolBuilder;

		layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
		layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
		poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);

		descriptorSetLayout		= layoutBuilder.build(vk, device);
		descriptorPool			= poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
		descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
	}

	// Create pipeline layout
	vk::Unique<vk::VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));

	// Create image views
	{
		imageViewSrc = createImageView(ctx, **imageSrc, vk::VK_FORMAT_R8G8B8A8_UNORM);
		imageViewDst = createImageView(ctx, **imageDst, vk::VK_FORMAT_R8G8B8A8_UNORM);
	}

	// Update descriptor set information
	{
		vk::DescriptorSetUpdateBuilder	updateBuilder;

		vk::VkDescriptorImageInfo		descStorageImgDst	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);
		vk::VkDescriptorImageInfo		descStorageImgSrc	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);

		updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
		updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgSrc);

		updateBuilder.update(vk, device);
	}

	// Create compute commands & submit
	{
		const vk::Unique<vk::VkFence>		fence		(vk::createFence(vk, device));
		vk::Unique<vk::VkPipeline>			pipeline	(makeComputePipeline(vk, device, *pipelineLayout, *computeShader, DE_NULL));
		vk::Unique<vk::VkCommandBuffer>		cmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));

		beginCommandBuffer(vk, *cmdBuffer);

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

		VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
	}

	// Calculate reference image
	calculateRef(*texture2D);

	// Validate result
	return validateResult(**imageDst, vk::VK_IMAGE_LAYOUT_GENERAL, *texture2D, refSampler);
}

void StackTestInstance::calculateRef (tcu::Texture2D& texture2D)
{
	const tcu::PixelBufferAccess&	reference	= texture2D.getLevel(0);
	const tcu::IVec4				zero;

	for (int x = 0; x < reference.getWidth(); ++x)
	for (int y = 0; y < reference.getHeight(); ++y)
		reference.setPixel(zero, x, y);
}

tcu::TestStatus StackTestInstance::validateResult (vk::VkImage image, vk::VkImageLayout imageLayout, const tcu::Texture2D& texture2D, const tcu::Sampler& refSampler)
{
	de::Random			rnd			(getSeedValue(m_params));
	ValidationData		refData;

	for (int ndx = 0; ndx < 4; ++ndx)
	{
		const float	lod	= 0.0f;
		const float	cx	= rnd.getFloat(0.0f, 1.0f);
		const float	cy	= rnd.getFloat(0.0f, 1.0f);

		refData.coords[ndx] = tcu::Vec4(cx, cy, 0.0f, 0.0f);
		refData.values[ndx] = texture2D.sample(refSampler, cx, cy, lod);
	}

	if (!m_validator.validateImage(m_protectedContext, refData, image, vk::VK_FORMAT_R8G8B8A8_UNORM, imageLayout))
		return tcu::TestStatus::fail("Result validation failed");
	else
		return tcu::TestStatus::pass("Pass");
}

} // anonymous

tcu::TestCaseGroup*	createStackTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> stackGroup (new tcu::TestCaseGroup(testCtx, "stack", "Protected memory stack tests"));

	static const deUint32 stackMemSizes[] = { 32, 64, 128, 256, 512, 1024 };

	for (int stackMemSizeIdx = 0; stackMemSizeIdx < DE_LENGTH_OF_ARRAY(stackMemSizes); ++stackMemSizeIdx)
	{
		std::string testName = std::string("stacksize_") + de::toString(stackMemSizes[stackMemSizeIdx]);

		stackGroup->addChild(new StackTestCase(testCtx, testName, "", Params(stackMemSizes[stackMemSizeIdx])));
	}

	return stackGroup.release();
}

} // ProtectedMem
} // vkt
