// 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"
#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::EmitState::getImageSampler(const vk::Device *device, uint32_t signature, uint32_t samplerId, uint32_t imageViewId)
{
	ImageInstructionSignature instruction(signature);
	ASSERT(imageViewId != 0 && (samplerId != 0 || instruction.samplerMethod == Fetch || instruction.samplerMethod == Write));
	ASSERT(device);

	vk::Device::SamplingRoutineCache::Key key = { signature, samplerId, imageViewId };

	auto createSamplingRoutine = [device](const vk::Device::SamplingRoutineCache::Key &key) {
		ImageInstructionSignature instruction(key.instruction);
		const vk::Identifier::State imageViewState = vk::Identifier(key.imageView).getState();
		const vk::SamplerState *vkSamplerState = (key.sampler != 0) ? device->findSampler(key.sampler) : nullptr;

		auto type = imageViewState.imageViewType;
		auto samplerMethod = static_cast<SamplerMethod>(instruction.samplerMethod);

		Sampler samplerState = {};
		samplerState.textureType = type;
		ASSERT(instruction.coordinates >= samplerState.dimensionality());  // "It may be a vector larger than needed, but all unused components appear after all used components."
		samplerState.textureFormat = imageViewState.format;

		samplerState.addressingModeU = convertAddressingMode(0, vkSamplerState, type);
		samplerState.addressingModeV = convertAddressingMode(1, vkSamplerState, type);
		samplerState.addressingModeW = convertAddressingMode(2, vkSamplerState, type);

		samplerState.mipmapFilter = convertMipmapMode(vkSamplerState);
		samplerState.swizzle = imageViewState.mapping;
		samplerState.gatherComponent = instruction.gatherComponent;

		if(vkSamplerState)
		{
			samplerState.textureFilter = convertFilterMode(vkSamplerState, type, samplerMethod);
			samplerState.border = vkSamplerState->borderColor;
			samplerState.customBorder = vkSamplerState->customBorderColor;

			samplerState.mipmapFilter = convertMipmapMode(vkSamplerState);
			samplerState.highPrecisionFiltering = (vkSamplerState->filteringPrecision == VK_SAMPLER_FILTERING_PRECISION_MODE_HIGH_GOOGLE);

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

			samplerState.ycbcrModel = vkSamplerState->ycbcrModel;
			samplerState.studioSwing = vkSamplerState->studioSwing;
			samplerState.swappedChroma = vkSamplerState->swappedChroma;

			samplerState.mipLodBias = vkSamplerState->mipLodBias;
			samplerState.maxAnisotropy = vkSamplerState->maxAnisotropy;
			samplerState.minLod = vkSamplerState->minLod;
			samplerState.maxLod = vkSamplerState->maxLod;

			// If there's a single mip level and filtering doesn't depend on the LOD level,
			// the sampler will need to compute the LOD to produce the proper result.
			// Otherwise, it can be ignored.
			// We can skip the LOD computation for all modes, except LOD query,
			// where we have to return the proper value even if nothing else requires it.
			if(imageViewState.singleMipLevel &&
			   (samplerState.textureFilter != FILTER_MIN_POINT_MAG_LINEAR) &&
			   (samplerState.textureFilter != FILTER_MIN_LINEAR_MAG_POINT) &&
			   (samplerMethod != Query))
			{
				samplerState.minLod = 0.0f;
				samplerState.maxLod = 0.0f;
			}
		}
		else if(samplerMethod == Fetch)
		{
			// OpImageFetch does not take a sampler descriptor, but for VK_EXT_image_robustness
			// requires replacing invalid texels with zero.
			// TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
			samplerState.border = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;

			// If there's a single mip level we can skip LOD computation.
			if(imageViewState.singleMipLevel)
			{
				samplerState.minLod = 0.0f;
				samplerState.maxLod = 0.0f;
			}
		}
		else if(samplerMethod == Write)
		{
			return emitWriteRoutine(instruction, samplerState);
		}
		else
			ASSERT(false);

		return emitSamplerRoutine(instruction, samplerState);
	};

	vk::Device::SamplingRoutineCache *cache = device->getSamplingRoutineCache();
	auto routine = cache->getOrCreate(key, createSamplingRoutine);

	return (ImageSampler *)(routine->getEntry());
}

std::shared_ptr<rr::Routine> SpirvShader::EmitState::emitWriteRoutine(ImageInstructionSignature instruction, const Sampler &samplerState)
{
	// TODO(b/129523279): Hold a separate mutex lock for the sampler being built.
	rr::Function<Void(Pointer<Byte>, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)> function;
	{
		Pointer<Byte> descriptor = function.Arg<0>();
		Pointer<SIMD::Float> coord = function.Arg<1>();
		Pointer<SIMD::Float> texelAndMask = function.Arg<2>();
		Pointer<Byte> constants = function.Arg<3>();

		WriteImage(instruction, descriptor, coord, texelAndMask, samplerState.textureFormat);
	}

	return function("sampler");
}

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

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

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

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

		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] = As<SIMD::Int>(in[i]);
		}

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

		SamplerCore s(constants, samplerState, samplerFunction);

		// 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.
		// TODO(b/133868964) Pass down 4 component lodOrBias, dsx, and dsy to sampleTexture
		if(samplerFunction.method == Lod || samplerFunction.method == Grad ||
		   samplerFunction.method == Bias || samplerFunction.method == Fetch)
		{
			// Only perform per-lane sampling if LOD diverges or we're doing Grad sampling.
			Bool perLaneSampling = (samplerFunction.method == Grad) || Divergent(As<SIMD::Int>(lodOrBias));
			auto lod = Pointer<Float>(&lodOrBias);
			Int i = 0;
			Do
			{
				SIMD::Float dPdx;
				SIMD::Float dPdy;
				dPdx.x = Pointer<Float>(&dsx[0])[i];
				dPdx.y = Pointer<Float>(&dsx[1])[i];
				dPdx.z = Pointer<Float>(&dsx[2])[i];

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

				SIMD::Float4 sample = s.sampleTexture(texture, uvwa, dRef, lod[i], dPdx, dPdy, offset, sampleId);

				If(perLaneSampling)
				{
					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];
					i++;
				}
				Else
				{
					Pointer<SIMD::Float> rgba = out;
					rgba[0] = sample.x;
					rgba[1] = sample.y;
					rgba[2] = sample.z;
					rgba[3] = sample.w;
					i = SIMD::Width;
				}
			}
			Until(i == SIMD::Width);
		}
		else
		{
			Float lod = Float(lodOrBias.x);
			SIMD::Float4 sample = s.sampleTexture(texture, uvwa, dRef, lod, (dsx[0]), (dsy[0]), offset, sampleId);

			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::EmitState::convertFilterMode(const vk::SamplerState *samplerState, VkImageViewType imageViewType, SamplerMethod samplerMethod)
{
	if(samplerMethod == Gather)
	{
		return FILTER_GATHER;
	}

	if(samplerMethod == Fetch)
	{
		return FILTER_POINT;
	}

	if(samplerState->anisotropyEnable != VK_FALSE)
	{
		if(imageViewType == VK_IMAGE_VIEW_TYPE_2D || imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
		{
			if(samplerMethod != Lod)  // TODO(b/162926129): Support anisotropic filtering with explicit LOD.
			{
				return FILTER_ANISOTROPIC;
			}
		}
	}

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

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

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

	if(samplerState->ycbcrModel != VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
	{
		// TODO(b/151263485): Check image view level count instead.
		return MIPMAP_NONE;
	}

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

sw::AddressingMode SpirvShader::EmitState::convertAddressingMode(int coordinateIndex, const vk::SamplerState *samplerState, VkImageViewType imageViewType)
{
	switch(imageViewType)
	{
	case VK_IMAGE_VIEW_TYPE_1D:
	case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
		if(coordinateIndex >= 1)
		{
			return ADDRESSING_UNUSED;
		}
		break;
	case VK_IMAGE_VIEW_TYPE_2D:
	case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
		if(coordinateIndex == 2)
		{
			return ADDRESSING_UNUSED;
		}
		break;

	case VK_IMAGE_VIEW_TYPE_3D:
		break;

	case VK_IMAGE_VIEW_TYPE_CUBE:
	case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
		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  // coordinateIndex == 2
		{
			// The cube face is an index into 2D array layers.
			return ADDRESSING_CUBEFACE;
		}
		break;

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

	if(!samplerState)
	{
		// OpImageFetch does not take a sampler descriptor, but still needs a valid
		// 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

		// VK_EXT_image_robustness requires nullifying out-of-bounds accesses.
		// ADDRESSING_BORDER causes texel replacement to be performed.
		// TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
		return ADDRESSING_BORDER;
	}

	VkSamplerAddressMode addressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
	switch(coordinateIndex)
	{
	case 0: addressMode = samplerState->addressModeU; break;
	case 1: addressMode = samplerState->addressModeV; break;
	case 2: addressMode = samplerState->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
