// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#include "SpirvShader.hpp"

#include "SamplerCore.hpp"  // TODO: Figure out what's needed.
#include "Device/Config.hpp"
#include "System/Debug.hpp"
#include "System/Math.hpp"
#include "Vulkan/VkDescriptorSetLayout.hpp"
#include "Vulkan/VkDevice.hpp"
#include "Vulkan/VkImageView.hpp"
#include "Vulkan/VkSampler.hpp"

#include <spirv/unified1/spirv.hpp>

#include <climits>
#include <mutex>

namespace sw {

SpirvShader::ImageSampler *SpirvShader::getImageSampler(uint32_t inst, vk::SampledImageDescriptor const *imageDescriptor, const vk::Sampler *sampler)
{
	ImageInstruction instruction(inst);
	const auto samplerId = sampler ? sampler->id : 0;
	ASSERT(imageDescriptor->imageViewId != 0 && (samplerId != 0 || instruction.samplerMethod == Fetch));

	vk::Device::SamplingRoutineCache::Key key = { inst, imageDescriptor->imageViewId, samplerId };

	ASSERT(imageDescriptor->device);

	if(auto routine = imageDescriptor->device->findInConstCache(key))
	{
		return (ImageSampler *)(routine->getEntry());
	}

	std::unique_lock<std::mutex> lock(imageDescriptor->device->getSamplingRoutineCacheMutex());
	vk::Device::SamplingRoutineCache *cache = imageDescriptor->device->getSamplingRoutineCache();

	auto routine = cache->query(key);
	if(routine)
	{
		return (ImageSampler *)(routine->getEntry());
	}

	auto type = imageDescriptor->type;

	Sampler samplerState = {};
	samplerState.textureType = type;
	samplerState.textureFormat = imageDescriptor->format;

	samplerState.addressingModeU = convertAddressingMode(0, sampler, type);
	samplerState.addressingModeV = convertAddressingMode(1, sampler, type);
	samplerState.addressingModeW = convertAddressingMode(2, sampler, type);
	samplerState.addressingModeY = convertAddressingMode(3, sampler, type);

	samplerState.mipmapFilter = convertMipmapMode(sampler);
	samplerState.swizzle = imageDescriptor->swizzle;
	samplerState.gatherComponent = instruction.gatherComponent;
	samplerState.highPrecisionFiltering = false;
	samplerState.largeTexture = (imageDescriptor->extent.width > SHRT_MAX) ||
	                            (imageDescriptor->extent.height > SHRT_MAX) ||
	                            (imageDescriptor->extent.depth > SHRT_MAX);

	if(sampler)
	{
		samplerState.textureFilter = (instruction.samplerMethod == Gather) ? FILTER_GATHER : convertFilterMode(sampler);
		samplerState.border = sampler->borderColor;

		samplerState.mipmapFilter = convertMipmapMode(sampler);

		samplerState.compareEnable = (sampler->compareEnable != VK_FALSE);
		samplerState.compareOp = sampler->compareOp;
		samplerState.unnormalizedCoordinates = (sampler->unnormalizedCoordinates != VK_FALSE);

		if(sampler->ycbcrConversion)
		{
			samplerState.ycbcrModel = sampler->ycbcrConversion->ycbcrModel;
			samplerState.studioSwing = (sampler->ycbcrConversion->ycbcrRange == VK_SAMPLER_YCBCR_RANGE_ITU_NARROW);
			samplerState.swappedChroma = (sampler->ycbcrConversion->components.r != VK_COMPONENT_SWIZZLE_R);
		}
	}

	routine = emitSamplerRoutine(instruction, samplerState);

	cache->add(key, routine);
	return (ImageSampler *)(routine->getEntry());
}

std::shared_ptr<rr::Routine> SpirvShader::emitSamplerRoutine(ImageInstruction instruction, const Sampler &samplerState)
{
	// TODO(b/129523279): Hold a separate mutex lock for the sampler being built.
	rr::Function<Void(Pointer<Byte>, Pointer<Byte>, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)> function;
	{
		Pointer<Byte> texture = function.Arg<0>();
		Pointer<Byte> sampler = function.Arg<1>();
		Pointer<SIMD::Float> in = function.Arg<2>();
		Pointer<SIMD::Float> out = function.Arg<3>();
		Pointer<Byte> constants = function.Arg<4>();

		SIMD::Float uvw[4] = { 0, 0, 0, 0 };
		SIMD::Float q = 0;
		SIMD::Float lodOrBias = 0;  // Explicit level-of-detail, or bias added to the implicit level-of-detail (depending on samplerMethod).
		Vector4f dsx = { 0, 0, 0, 0 };
		Vector4f dsy = { 0, 0, 0, 0 };
		Vector4f offset = { 0, 0, 0, 0 };
		SIMD::Int sampleId = 0;
		SamplerFunction samplerFunction = instruction.getSamplerFunction();

		uint32_t i = 0;
		for(; i < instruction.coordinates; i++)
		{
			uvw[i] = in[i];
		}

		if(instruction.isDref())
		{
			q = in[i];
			i++;
		}

		// TODO(b/134669567): Currently 1D textures are treated as 2D by setting the second coordinate to 0.
		// Implement optimized 1D sampling.
		if(samplerState.textureType == VK_IMAGE_VIEW_TYPE_1D)
		{
			uvw[1] = SIMD::Float(0);
		}
		else if(samplerState.textureType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
		{
			uvw[1] = SIMD::Float(0);
			uvw[2] = in[1];  // Move 1D layer coordinate to 2D layer coordinate index.
		}

		if(instruction.samplerMethod == Lod || instruction.samplerMethod == Bias || instruction.samplerMethod == Fetch)
		{
			lodOrBias = in[i];
			i++;
		}
		else if(instruction.samplerMethod == Grad)
		{
			for(uint32_t j = 0; j < instruction.grad; j++, i++)
			{
				dsx[j] = in[i];
			}

			for(uint32_t j = 0; j < instruction.grad; j++, i++)
			{
				dsy[j] = in[i];
			}
		}

		for(uint32_t j = 0; j < instruction.offset; j++, i++)
		{
			offset[j] = in[i];
		}

		if(instruction.sample)
		{
			sampleId = As<SIMD::Int>(in[i]);
		}

		SamplerCore s(constants, samplerState);

		// For explicit-lod instructions the LOD can be different per SIMD lane. SamplerCore currently assumes
		// a single LOD per four elements, so we sample the image again for each LOD separately.
		if(samplerFunction.method == Lod || samplerFunction.method == Grad)  // TODO(b/133868964): Also handle divergent Bias and Fetch with Lod.
		{
			auto lod = Pointer<Float>(&lodOrBias);

			For(Int i = 0, i < SIMD::Width, i++)
			{
				SIMD::Float dPdx;
				SIMD::Float dPdy;

				dPdx.x = Pointer<Float>(&dsx.x)[i];
				dPdx.y = Pointer<Float>(&dsx.y)[i];
				dPdx.z = Pointer<Float>(&dsx.z)[i];

				dPdy.x = Pointer<Float>(&dsy.x)[i];
				dPdy.y = Pointer<Float>(&dsy.y)[i];
				dPdy.z = Pointer<Float>(&dsy.z)[i];

				// 1D textures are treated as 2D texture with second coordinate 0, so we also need to zero out the second grad component. TODO(b/134669567)
				if(samplerState.textureType == VK_IMAGE_VIEW_TYPE_1D || samplerState.textureType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
				{
					dPdx.y = Float(0.0f);
					dPdy.y = Float(0.0f);
				}

				Vector4f sample = s.sampleTexture(texture, sampler, uvw, q, lod[i], dPdx, dPdy, offset, sampleId, samplerFunction);

				Pointer<Float> rgba = out;
				rgba[0 * SIMD::Width + i] = Pointer<Float>(&sample.x)[i];
				rgba[1 * SIMD::Width + i] = Pointer<Float>(&sample.y)[i];
				rgba[2 * SIMD::Width + i] = Pointer<Float>(&sample.z)[i];
				rgba[3 * SIMD::Width + i] = Pointer<Float>(&sample.w)[i];
			}
		}
		else
		{
			Vector4f sample = s.sampleTexture(texture, sampler, uvw, q, lodOrBias.x, (dsx.x), (dsy.x), offset, sampleId, samplerFunction);

			Pointer<SIMD::Float> rgba = out;
			rgba[0] = sample.x;
			rgba[1] = sample.y;
			rgba[2] = sample.z;
			rgba[3] = sample.w;
		}
	}

	return function("sampler");
}

sw::FilterType SpirvShader::convertFilterMode(const vk::Sampler *sampler)
{
	if(sampler->anisotropyEnable != VK_FALSE)
	{
		return FILTER_ANISOTROPIC;
	}

	switch(sampler->magFilter)
	{
		case VK_FILTER_NEAREST:
			switch(sampler->minFilter)
			{
				case VK_FILTER_NEAREST: return FILTER_POINT;
				case VK_FILTER_LINEAR: return FILTER_MIN_LINEAR_MAG_POINT;
				default:
					UNSUPPORTED("minFilter %d", sampler->minFilter);
					return FILTER_POINT;
			}
			break;
		case VK_FILTER_LINEAR:
			switch(sampler->minFilter)
			{
				case VK_FILTER_NEAREST: return FILTER_MIN_POINT_MAG_LINEAR;
				case VK_FILTER_LINEAR: return FILTER_LINEAR;
				default:
					UNSUPPORTED("minFilter %d", sampler->minFilter);
					return FILTER_POINT;
			}
			break;
		default:
			break;
	}

	UNSUPPORTED("magFilter %d", sampler->magFilter);
	return FILTER_POINT;
}

sw::MipmapType SpirvShader::convertMipmapMode(const vk::Sampler *sampler)
{
	if(!sampler)
	{
		return MIPMAP_POINT;  // Samplerless operations (OpImageFetch) can take an integer Lod operand.
	}

	if(sampler->ycbcrConversion)
	{
		return MIPMAP_NONE;  // YCbCr images can only have one mipmap level.
	}

	switch(sampler->mipmapMode)
	{
		case VK_SAMPLER_MIPMAP_MODE_NEAREST: return MIPMAP_POINT;
		case VK_SAMPLER_MIPMAP_MODE_LINEAR: return MIPMAP_LINEAR;
		default:
			UNSUPPORTED("mipmapMode %d", sampler->mipmapMode);
			return MIPMAP_POINT;
	}
}

sw::AddressingMode SpirvShader::convertAddressingMode(int coordinateIndex, const vk::Sampler *sampler, VkImageViewType imageViewType)
{
	switch(imageViewType)
	{
		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
			if(coordinateIndex == 3)
			{
				return ADDRESSING_LAYER;
			}
			// Fall through to CUBE case:
		case VK_IMAGE_VIEW_TYPE_CUBE:
			if(coordinateIndex <= 1)  // Cube faces themselves are addressed as 2D images.
			{
				// Vulkan 1.1 spec:
				// "Cube images ignore the wrap modes specified in the sampler. Instead, if VK_FILTER_NEAREST is used within a mip level then
				//  VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE is used, and if VK_FILTER_LINEAR is used within a mip level then sampling at the edges
				//  is performed as described earlier in the Cube map edge handling section."
				// This corresponds with our 'SEAMLESS' addressing mode.
				return ADDRESSING_SEAMLESS;
			}
			else if(coordinateIndex == 2)
			{
				// The cube face is an index into array layers.
				return ADDRESSING_CUBEFACE;
			}
			else
			{
				return ADDRESSING_UNUSED;
			}
			break;

		case VK_IMAGE_VIEW_TYPE_1D:  // Treated as 2D texture with second coordinate 0. TODO(b/134669567)
			if(coordinateIndex == 1)
			{
				return ADDRESSING_WRAP;
			}
			else if(coordinateIndex >= 2)
			{
				return ADDRESSING_UNUSED;
			}
			break;

		case VK_IMAGE_VIEW_TYPE_3D:
			if(coordinateIndex >= 3)
			{
				return ADDRESSING_UNUSED;
			}
			break;

		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:  // Treated as 2D texture with second coordinate 0. TODO(b/134669567)
			if(coordinateIndex == 1)
			{
				return ADDRESSING_WRAP;
			}
			// Fall through to 2D_ARRAY case:
		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
			if(coordinateIndex == 2)
			{
				return ADDRESSING_LAYER;
			}
			else if(coordinateIndex >= 3)
			{
				return ADDRESSING_UNUSED;
			}
			// Fall through to 2D case:
		case VK_IMAGE_VIEW_TYPE_2D:
			if(coordinateIndex >= 2)
			{
				return ADDRESSING_UNUSED;
			}
			break;

		default:
			UNSUPPORTED("imageViewType %d", imageViewType);
			return ADDRESSING_WRAP;
	}

	if(!sampler)
	{
		// OpImageFetch does not take a sampler descriptor, but still needs a valid,
		// arbitrary addressing mode that prevents out-of-bounds accesses:
		// "The value returned by a read of an invalid texel is undefined, unless that
		//  read operation is from a buffer resource and the robustBufferAccess feature
		//  is enabled. In that case, an invalid texel is replaced as described by the
		//  robustBufferAccess feature." - Vulkan 1.1

		return ADDRESSING_WRAP;
	}

	VkSamplerAddressMode addressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
	switch(coordinateIndex)
	{
		case 0: addressMode = sampler->addressModeU; break;
		case 1: addressMode = sampler->addressModeV; break;
		case 2: addressMode = sampler->addressModeW; break;
		default: UNSUPPORTED("coordinateIndex: %d", coordinateIndex);
	}

	switch(addressMode)
	{
		case VK_SAMPLER_ADDRESS_MODE_REPEAT: return ADDRESSING_WRAP;
		case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return ADDRESSING_MIRROR;
		case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return ADDRESSING_CLAMP;
		case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return ADDRESSING_BORDER;
		case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return ADDRESSING_MIRRORONCE;
		default:
			UNSUPPORTED("addressMode %d", addressMode);
			return ADDRESSING_WRAP;
	}
}

}  // namespace sw
