// Copyright 2022 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 "SwiftConfig.hpp"
#include "CPUID.hpp"
#include "Configurator.hpp"
#include "Debug.hpp"

#include "marl/scheduler.h"

#include <algorithm>

namespace {

std::string toLowerStr(const std::string &str)
{
	std::string lower = str;
	std::transform(lower.begin(), lower.end(), lower.begin(),
	               [](unsigned char c) { return std::tolower(c); });
	return lower;
}

marl::Thread::Core getCoreFromIndex(uint8_t coreIndex)
{
	marl::Thread::Core core = {};
#if defined(_WIN32)
	// We only support one processor group on Windows
	// when an explicit affinity mask is used.
	core.windows.group = 0;
	core.windows.index = coreIndex;
#else
	core.pthread.index = coreIndex;
#endif
	return core;
}

marl::Thread::Affinity getAffinityFromMask(uint64_t affinityMask)
{
	if(affinityMask == std::numeric_limits<uint64_t>::max())
	{
		return marl::Thread::Affinity::all();
	}

	ASSERT(affinityMask != 0);
	marl::containers::vector<marl::Thread::Core, 32> cores;
	uint8_t coreIndex = 0;
	while(affinityMask)
	{
		if(affinityMask & 1)
		{
			cores.push_back(getCoreFromIndex(coreIndex));
		}
		++coreIndex;
		affinityMask >>= 1;
	}

	return marl::Thread::Affinity(cores, marl::Allocator::Default);
}

std::shared_ptr<marl::Thread::Affinity::Policy> getAffinityPolicy(marl::Thread::Affinity &&affinity, sw::Configuration::AffinityPolicy affinityPolicy)
{
	switch(affinityPolicy)
	{
	case sw::Configuration::AffinityPolicy::AnyOf:
		return marl::Thread::Affinity::Policy::anyOf(std::move(affinity));
	case sw::Configuration::AffinityPolicy::OneOf:
		return marl::Thread::Affinity::Policy::oneOf(std::move(affinity));
	default:
		UNREACHABLE("unknown affinity policy");
	}
	return nullptr;
}
}  // namespace

namespace sw {

Configuration readConfigurationFromFile()
{
	Configurator ini("SwiftShader.ini");
	Configuration config{};

	// Processor flags.
	config.threadCount = ini.getInteger<uint32_t>("Processor", "ThreadCount", 0);
	config.affinityMask = ini.getInteger<uint64_t>("Processor", "AffinityMask", 0xffffffffffffffff);
	if(config.affinityMask == 0)
	{
		warn("Affinity mask is empty, using all-cores affinity\n");
		config.affinityMask = 0xffffffffffffffff;
	}
	std::string affinityPolicy = toLowerStr(ini.getValue("Processor", "AffinityPolicy", "any"));
	if(affinityPolicy == "one")
	{
		config.affinityPolicy = Configuration::AffinityPolicy::OneOf;
	}
	else
	{
		// Default.
		config.affinityPolicy = Configuration::AffinityPolicy::AnyOf;
	}

	// Debug flags.
	config.asmEmitDir = ini.getValue("Debug", "AsmEmitDir");
	if(config.asmEmitDir.size() > 0 && *config.asmEmitDir.rend() != '/')
	{
		config.asmEmitDir.push_back('/');
	}

	// Profiling flags.
	config.enableSpirvProfiling = ini.getBoolean("Profiler", "EnableSpirvProfiling");
	config.spvProfilingReportPeriodMs = ini.getInteger<uint64_t>("Profiler", "SpirvProfilingReportPeriodMs");
	config.spvProfilingReportDir = ini.getValue("Profiler", "SpirvProfilingReportDir");

	return config;
}

const Configuration &getConfiguration()
{
	static Configuration config = readConfigurationFromFile();
	return config;
}

marl::Scheduler::Config getSchedulerConfiguration(const Configuration &config)
{
	uint32_t threadCount = (config.threadCount == 0) ? std::min<size_t>(marl::Thread::numLogicalCPUs(), 16)
	                                                 : config.threadCount;
	auto affinity = getAffinityFromMask(config.affinityMask);
	auto affinityPolicy = getAffinityPolicy(std::move(affinity), config.affinityPolicy);

	marl::Scheduler::Config cfg;
	cfg.setWorkerThreadCount(threadCount);
	cfg.setWorkerThreadAffinityPolicy(affinityPolicy);
	cfg.setWorkerThreadInitializer([](int) {
		sw::CPUID::setFlushToZero(true);
		sw::CPUID::setDenormalsAreZero(true);
	});
	return cfg;
}

rr::DebugConfig getReactorDebugConfig(const Configuration &config)
{
	rr::DebugConfig debugCfg;
	debugCfg.asmEmitDir = config.asmEmitDir;
	return debugCfg;
}
}  // namespace sw