// 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 "System/Math.hpp"
#include "Vulkan/VkDebug.hpp"
#include "Vulkan/VkDescriptorSetLayout.hpp"
#include "Vulkan/VkDevice.hpp"
#include "Vulkan/VkImageView.hpp"
#include "Vulkan/VkSampler.hpp"
#include "Device/Config.hpp"

#include <spirv/unified1/spirv.hpp>
#include <spirv/unified1/GLSL.std.450.h>

#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.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_TRUE);
		samplerState.compareOp = sampler->compareOp;
		samplerState.unnormalizedCoordinates = (sampler->unnormalizedCoordinates == VK_TRUE);

		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);
		}

		if(sampler->anisotropyEnable != VK_FALSE)
		{
			UNSUPPORTED("anisotropyEnable");
		}
	}

	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[0], uvw[1], uvw[2], 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[0], uvw[1], uvw[2], 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)
{
	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:
			UNIMPLEMENTED("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:
			UNIMPLEMENTED("minFilter %d", sampler->minFilter);
			return FILTER_POINT;
		}
		break;
	default:
		break;
	}

	UNIMPLEMENTED("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:
		UNIMPLEMENTED("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:
		UNSUPPORTED("SPIR-V ImageCubeArray Capability (imageViewType: %d)", int(imageViewType));
		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:
		UNIMPLEMENTED("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:
		UNIMPLEMENTED("addressMode %d", addressMode);
		return ADDRESSING_WRAP;
	}
}

} // namespace sw
