<commit_before>#include "RenderTileMap.h"
#include "Profiler.h"
#include "RenderContext.h"
#include "RenderTile.h"
#include "math/Generator.h"

#include "Logger.h"
namespace PR {
RenderTileMap::RenderTileMap()
	: mTileMap()
{
}

RenderTileMap::~RenderTileMap()
{
	clearMap();
}

void RenderTileMap::clearMap()
{
	Mutex::scoped_lock lock(mMutex, true);
	for (auto tile : mTileMap)
		delete tile;

	mTileMap.clear();
}

void RenderTileMap::init(const RenderContext& context, uint32 threadcount, TileMode mode)
{
	PR_PROFILE_THIS;

	int32 initial_count = std::max<int32>(1, threadcount / 2);

	mMaxTileSize		= context.viewSize();
	mMaxTileSize.Width  = std::max(2, mMaxTileSize.Width / initial_count);
	mMaxTileSize.Height = std::max(2, mMaxTileSize.Height / initial_count);

	const Size1i tx = std::max<int32>(2, std::ceil(context.viewSize().Width / (float)mMaxTileSize.Width));
	const Size1i ty = std::max<int32>(2, std::ceil(context.viewSize().Height / (float)mMaxTileSize.Height));

	// Clear previous data
	clearMap();

	// New data
	mTileMap.reserve(tx * ty);
	auto addTile = [&](Point1i sx, Point1i sy) {
		Point2i start = Point2i(sx, sy);
		Point2i end   = (start + mMaxTileSize).cwiseMin(Point2i(context.viewSize().Width, context.viewSize().Height));
		auto tile	 = new RenderTile(start, end, context);
		mTileMap.emplace_back(tile);
	};

	switch (mode) {
	default:
	case TM_LINEAR:
		for (Point1i i = 0; i < ty; ++i) {
			for (Point1i j = 0; j < tx; ++j) {
				Point1i sx = j * mMaxTileSize.Width;
				Point1i sy = i * mMaxTileSize.Height;

				if (sx < context.viewSize().Width - 1
					&& sy < context.viewSize().Height - 1)
					addTile(sx, sy);
			}
		}
		break;
	case TM_TILE:
		// Even
		for (Point1i i = 0; i < ty; ++i) {
			for (Point1i j = ((i % 2) ? 1 : 0); j < tx; j += 2) {
				Point1i sx = j * mMaxTileSize.Width;
				Point1i sy = i * mMaxTileSize.Height;

				if (sx < context.viewSize().Width - 1
					&& sy < context.viewSize().Height - 1)
					addTile(sx, sy);
			}
			// Odd
			for (Point1i i = 0; i < ty; ++i) {
				for (Point1i j = ((i % 2) ? 0 : 1); j < tx; j += 2) {
					Point1i sx = j * mMaxTileSize.Width;
					Point1i sy = i * mMaxTileSize.Height;

					if (sx < context.viewSize().Width - 1
						&& sy < context.viewSize().Height - 1)
						addTile(sx, sy);
				}
			}
		}
		break;
	case TM_SPIRAL: {
		MinRadiusGenerator<2> generator(std::max(tx / 2, ty / 2));
		while (generator.hasNext()) {
			const auto p   = generator.next();
			const auto itx = tx / 2 + p[0];
			const auto ity = ty / 2 + p[1];

			if (itx < tx && ity < ty) {
				if (itx * mMaxTileSize.Width < context.viewSize().Width - 1
					&& ity * mMaxTileSize.Height < context.viewSize().Height - 1)
					addTile(itx * mMaxTileSize.Width,
							ity * mMaxTileSize.Height);
			}
		}
	} break;
	}
}

RenderTile* RenderTileMap::getNextTile(uint32 maxIter)
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	for (auto tile : mTileMap)
		if (tile && tile->iterationCount() < maxIter && !tile->isFinished())
			if (tile->accuire())
				return tile;

	return nullptr;
}

bool RenderTileMap::allFinished() const
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	for (auto tile : mTileMap)
		if (!tile->isFinished() || tile->isWorking())
			return false;
	return true;
}

RenderTileStatistics RenderTileMap::statistics() const
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	RenderTileStatistics s;
	for (auto tile : mTileMap)
		s += tile->statistics();
	return s;
}

float RenderTileMap::percentage() const
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	uint32 maxSamples	  = 0;
	uint32 samplesRendered = 0;
	for (auto tile : mTileMap) {
		maxSamples += tile->maxPixelSamples();
		samplesRendered += tile->pixelSamplesRendered();
	}

	if (maxSamples == 0)
		return 1.0f;
	else
		return samplesRendered / (float)maxSamples;
}

void RenderTileMap::reset()
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	for (auto tile : mTileMap)
		tile->reset();
}

void RenderTileMap::optimize()
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, true);
	constexpr Size1i MinTileSize = 4;
	constexpr int64 MinTimeSpent = 10000; // 10ms

	int64 fullWorkTime = 0;
	int64 validTiles   = 0;
	for (auto tile : mTileMap) {
		if (tile->lastWorkTime().count() > 0) {<commit_msg>Made tile adapting more conservative<commit_after>#include "RenderTileMap.h"
#include "Profiler.h"
#include "RenderContext.h"
#include "RenderTile.h"
#include "math/Generator.h"

#include "Logger.h"
namespace PR {
RenderTileMap::RenderTileMap()
	: mTileMap()
{
}

RenderTileMap::~RenderTileMap()
{
	clearMap();
}

void RenderTileMap::clearMap()
{
	Mutex::scoped_lock lock(mMutex, true);
	for (auto tile : mTileMap)
		delete tile;

	mTileMap.clear();
}

void RenderTileMap::init(const RenderContext& context, uint32 threadcount, TileMode mode)
{
	PR_PROFILE_THIS;

	int32 initial_count = std::max<int32>(1, threadcount / 2);

	mMaxTileSize		= context.viewSize();
	mMaxTileSize.Width  = std::max(2, mMaxTileSize.Width / initial_count);
	mMaxTileSize.Height = std::max(2, mMaxTileSize.Height / initial_count);

	const Size1i tx = std::max<int32>(2, std::ceil(context.viewSize().Width / (float)mMaxTileSize.Width));
	const Size1i ty = std::max<int32>(2, std::ceil(context.viewSize().Height / (float)mMaxTileSize.Height));

	// Clear previous data
	clearMap();

	// New data
	mTileMap.reserve(tx * ty);
	auto addTile = [&](Point1i sx, Point1i sy) {
		Point2i start = Point2i(sx, sy);
		Point2i end   = (start + mMaxTileSize).cwiseMin(Point2i(context.viewSize().Width, context.viewSize().Height));
		auto tile	 = new RenderTile(start, end, context);
		mTileMap.emplace_back(tile);
	};

	switch (mode) {
	default:
	case TM_LINEAR:
		for (Point1i i = 0; i < ty; ++i) {
			for (Point1i j = 0; j < tx; ++j) {
				Point1i sx = j * mMaxTileSize.Width;
				Point1i sy = i * mMaxTileSize.Height;

				if (sx < context.viewSize().Width - 1
					&& sy < context.viewSize().Height - 1)
					addTile(sx, sy);
			}
		}
		break;
	case TM_TILE:
		// Even
		for (Point1i i = 0; i < ty; ++i) {
			for (Point1i j = ((i % 2) ? 1 : 0); j < tx; j += 2) {
				Point1i sx = j * mMaxTileSize.Width;
				Point1i sy = i * mMaxTileSize.Height;

				if (sx < context.viewSize().Width - 1
					&& sy < context.viewSize().Height - 1)
					addTile(sx, sy);
			}
			// Odd
			for (Point1i i = 0; i < ty; ++i) {
				for (Point1i j = ((i % 2) ? 0 : 1); j < tx; j += 2) {
					Point1i sx = j * mMaxTileSize.Width;
					Point1i sy = i * mMaxTileSize.Height;

					if (sx < context.viewSize().Width - 1
						&& sy < context.viewSize().Height - 1)
						addTile(sx, sy);
				}
			}
		}
		break;
	case TM_SPIRAL: {
		MinRadiusGenerator<2> generator(std::max(tx / 2, ty / 2));
		while (generator.hasNext()) {
			const auto p   = generator.next();
			const auto itx = tx / 2 + p[0];
			const auto ity = ty / 2 + p[1];

			if (itx < tx && ity < ty) {
				if (itx * mMaxTileSize.Width < context.viewSize().Width - 1
					&& ity * mMaxTileSize.Height < context.viewSize().Height - 1)
					addTile(itx * mMaxTileSize.Width,
							ity * mMaxTileSize.Height);
			}
		}
	} break;
	}
}

RenderTile* RenderTileMap::getNextTile(uint32 maxIter)
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	for (auto tile : mTileMap)
		if (tile && tile->iterationCount() < maxIter && !tile->isFinished())
			if (tile->accuire())
				return tile;

	return nullptr;
}

bool RenderTileMap::allFinished() const
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	for (auto tile : mTileMap)
		if (!tile->isFinished() || tile->isWorking())
			return false;
	return true;
}

RenderTileStatistics RenderTileMap::statistics() const
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	RenderTileStatistics s;
	for (auto tile : mTileMap)
		s += tile->statistics();
	return s;
}

float RenderTileMap::percentage() const
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	uint32 maxSamples	  = 0;
	uint32 samplesRendered = 0;
	for (auto tile : mTileMap) {
		maxSamples += tile->maxPixelSamples();
		samplesRendered += tile->pixelSamplesRendered();
	}

	if (maxSamples == 0)
		return 1.0f;
	else
		return samplesRendered / (float)maxSamples;
}

void RenderTileMap::reset()
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, false);
	for (auto tile : mTileMap)
		tile->reset();
}

void RenderTileMap::optimize()
{
	PR_PROFILE_THIS;

	Mutex::scoped_lock lock(mMutex, true);
	constexpr Size1i MinTileSize = 8;
	constexpr int64 MinTimeSpent = 5 * 1000 * 1000; // 5s

	int64 fullWorkTime = 0;
	int64 validTiles   = 0;
	for (auto tile : mTileMap) {
		if (tile->lastWorkTime().count() > 0) {
{'fraction_non_alphanumeric': 0.1521964718090626, 'fraction_numerical': 0.021561166839617202, 'mean_word_length': 3.681057744198597, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1995780', 'n_tokens_mistral': 3739, 'n_tokens_neox': 3324, 'n_words': 762}