// Copyright 2016 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 "PixelProcessor.hpp"

#include "Primitive.hpp"
#include "Pipeline/Constants.hpp"
#include "Pipeline/PixelProgram.hpp"
#include "System/Debug.hpp"
#include "Vulkan/VkImageView.hpp"
#include "Vulkan/VkPipelineLayout.hpp"

#include <cstring>

namespace sw {

uint32_t PixelProcessor::States::computeHash()
{
	uint32_t *state = reinterpret_cast<uint32_t *>(this);
	uint32_t hash = 0;

	for(unsigned int i = 0; i < sizeof(States) / sizeof(uint32_t); i++)
	{
		hash ^= state[i];
	}

	return hash;
}

bool PixelProcessor::State::operator==(const State &state) const
{
	if(hash != state.hash)
	{
		return false;
	}

	return *static_cast<const States *>(this) == static_cast<const States &>(state);
}

PixelProcessor::PixelProcessor()
{
	setRoutineCacheSize(1024);
}

void PixelProcessor::setBlendConstant(const float4 &blendConstant)
{
	for(int i = 0; i < 4; i++)
	{
		factor.blendConstantF[i] = blendConstant[i];
		factor.invBlendConstantF[i] = 1.0f - blendConstant[i];
		factor.blendConstantU[i] = clamp(blendConstant[i], 0.0f, 1.0f);
		factor.invBlendConstantU[i] = 1.0f - clamp(blendConstant[i], 0.0f, 1.0f);
		factor.blendConstantS[i] = clamp(blendConstant[i], -1.0f, 1.0f);
		factor.invBlendConstantS[i] = 1.0f - clamp(blendConstant[i], -1.0f, 1.0f);
	}
}

void PixelProcessor::setRoutineCacheSize(int cacheSize)
{
	routineCache = std::make_unique<RoutineCacheType>(clamp(cacheSize, 1, 65536));
}

const PixelProcessor::State PixelProcessor::update(const vk::GraphicsState &pipelineState, const sw::SpirvShader *fragmentShader, const sw::SpirvShader *vertexShader, const vk::Attachments &attachments, bool occlusionEnabled) const
{
	const vk::VertexInputInterfaceState &vertexInputInterfaceState = pipelineState.getVertexInputInterfaceState();
	const vk::PreRasterizationState &preRasterizationState = pipelineState.getPreRasterizationState();
	const vk::FragmentState &fragmentState = pipelineState.getFragmentState();
	const vk::FragmentOutputInterfaceState &fragmentOutputInterfaceState = pipelineState.getFragmentOutputInterfaceState();

	State state;

	state.numClipDistances = vertexShader->getNumOutputClipDistances();
	state.numCullDistances = vertexShader->getNumOutputCullDistances();

	if(fragmentShader)
	{
		state.shaderID = fragmentShader->getIdentifier();
		state.pipelineLayoutIdentifier = fragmentState.getPipelineLayout()->identifier;
		state.robustBufferAccess = fragmentShader->getRobustBufferAccess();
	}
	else
	{
		state.shaderID = 0;
		state.pipelineLayoutIdentifier = 0;
		state.robustBufferAccess = false;
	}

	state.alphaToCoverage = fragmentOutputInterfaceState.hasAlphaToCoverage();
	state.depthWriteEnable = fragmentState.depthWriteActive(attachments);

	if(fragmentState.stencilActive(attachments))
	{
		state.stencilActive = true;
		state.frontStencil = fragmentState.getFrontStencil();
		state.backStencil = fragmentState.getBackStencil();
	}

	state.depthFormat = attachments.depthFormat();
	state.depthBoundsTestActive = fragmentState.depthBoundsTestActive(attachments);
	state.minDepthBounds = fragmentState.getMinDepthBounds();
	state.maxDepthBounds = fragmentState.getMaxDepthBounds();

	if(fragmentState.depthTestActive(attachments))
	{
		state.depthTestActive = true;
		state.depthCompareMode = fragmentState.getDepthCompareMode();

		state.depthBias = preRasterizationState.getConstantDepthBias() != 0.0f || preRasterizationState.getSlopeDepthBias() != 0.0f;

		bool pipelineDepthClamp = preRasterizationState.getDepthClampEnable();
		// "For fixed-point depth buffers, fragment depth values are always limited to the range [0,1] by clamping after depth bias addition is performed.
		//  Unless the VK_EXT_depth_range_unrestricted extension is enabled, fragment depth values are clamped even when the depth buffer uses a floating-point representation."
		state.depthClamp = pipelineDepthClamp || !state.depthFormat.isFloatFormat() || !preRasterizationState.hasDepthRangeUnrestricted();

		if(pipelineDepthClamp)
		{
			const VkViewport viewport = preRasterizationState.getViewport();
			state.minDepthClamp = min(viewport.minDepth, viewport.maxDepth);
			state.maxDepthClamp = max(viewport.minDepth, viewport.maxDepth);
		}
		else if(state.depthClamp)
		{
			state.minDepthClamp = 0.0f;
			state.maxDepthClamp = 1.0f;
		}
	}

	state.occlusionEnabled = occlusionEnabled;

	bool fragmentContainsDiscard = (fragmentShader && fragmentShader->getAnalysis().ContainsDiscard);
	for(int i = 0; i < MAX_COLOR_BUFFERS; i++)
	{
		state.colorWriteMask |= fragmentOutputInterfaceState.colorWriteActive(i, attachments) << (4 * i);
		state.colorFormat[i] = attachments.colorFormat(i);
		state.blendState[i] = fragmentOutputInterfaceState.getBlendState(i, attachments, fragmentContainsDiscard);
	}

	const bool isBresenhamLine = vertexInputInterfaceState.isDrawLine(true, preRasterizationState.getPolygonMode()) &&
	                             preRasterizationState.getLineRasterizationMode() == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;

	state.multiSampleCount = static_cast<unsigned int>(fragmentOutputInterfaceState.getSampleCount());
	state.multiSampleMask = fragmentOutputInterfaceState.getMultiSampleMask();
	state.enableMultiSampling = state.multiSampleCount > 1 && !isBresenhamLine;

	// SampleId and SamplePosition require per-sample fragment shader invocations, so the Vulkan spec
	// requires turning on sample shading if either of them is present in the shader:
	// "If a fragment shader entry point's interface includes an input variable decorated with SampleId,
	//  Sample Shading is considered enabled with a minSampleShading value of 1.0."
	// "If a fragment shader entry point's interface includes an input variable decorated with SamplePosition,
	//  Sample Shading is considered enabled with a minSampleShading value of 1.0."
	bool shaderContainsSampleDecoration = fragmentShader && (fragmentShader->hasBuiltinInput(spv::BuiltInSampleId) ||
	                                                         fragmentShader->hasBuiltinInput(spv::BuiltInSamplePosition));

	if(shaderContainsSampleDecoration)
	{
		state.sampleShadingEnabled = true;
		state.minSampleShading = 1.0f;
	}
	else
	{
		state.sampleShadingEnabled = fragmentOutputInterfaceState.hasSampleShadingEnabled();
		state.minSampleShading = fragmentOutputInterfaceState.getMinSampleShading();
	}

	if(state.enableMultiSampling && fragmentShader)
	{
		state.centroid = fragmentShader->getAnalysis().NeedsCentroid;
	}

	state.frontFace = preRasterizationState.getFrontFace();

	state.hash = state.computeHash();

	return state;
}

PixelProcessor::RoutineType PixelProcessor::routine(const State &state,
                                                    const vk::PipelineLayout *pipelineLayout,
                                                    const SpirvShader *pixelShader,
                                                    const vk::DescriptorSet::Bindings &descriptorSets)
{
	auto routine = routineCache->lookup(state);

	if(!routine)
	{
		QuadRasterizer *generator = new PixelProgram(state, pipelineLayout, pixelShader, descriptorSets);
		generator->generate();
		routine = (*generator)("PixelRoutine_%0.8X", state.shaderID);
		delete generator;

		routineCache->add(state, routine);
	}

	return routine;
}

}  // namespace sw
