Browse Source

Added font texture atlas benchmarks.

Lê Duy Quang 10 months ago
parent
commit
fa299f9cf1

BIN
Samples/assets/NotoSansJP-Regular.ttf


+ 2 - 2
Source/Core/FontEngineDefault/FontFaceLayer.cpp

@@ -221,9 +221,9 @@ bool FontFaceLayer::Generate(
 	return true;
 }
 
-bool FontFaceLayer::GenerateTexture(Vector<byte>& texture_data, Vector2i& texture_dimensions, int texture_id, const FontGlyphMap& glyphs)
+bool FontFaceLayer::GenerateTexture(Vector<byte>& texture_data, Vector2i& texture_dimensions, int texture_id, const FontGlyphMap& /*glyphs*/)
 {
-	if (texture_id < 0 || texture_id > sprite_set_textures.size())
+	if (texture_id < 0 || texture_id > static_cast<int>(sprite_set_textures.size()))
 		return false;
 
 	const unsigned char *const source = sprite_set_textures[texture_id];

+ 5 - 26
Source/Core/FontEngineDefault/SpriteSet.cpp

@@ -120,9 +120,9 @@ SpriteSet::Handle SpriteSet::Add(
 	)
 	{
 		auto texture_start = page.texture_data->begin() + (top_padding_y * page_size + slot.x) * bytes_per_pixel;
-		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, 0);
+		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, static_cast<unsigned char>(0));
 		texture_start = page.texture_data->begin() + (bottom_padding_y * page_size + slot.x) * bytes_per_pixel;
-		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, 0);
+		std::fill(texture_start, texture_start + padded_width * bytes_per_pixel, static_cast<unsigned char>(0));
 	}
 	const unsigned int texture_y = shelf.y + sprite_padding;
 	for (unsigned int local_y = 0; local_y != height; ++local_y)
@@ -130,9 +130,10 @@ SpriteSet::Handle SpriteSet::Add(
 		const unsigned char* const data_start = data + local_y * row_stride * bytes_per_pixel;
 		const auto texture_start = page.texture_data->begin()
 			+ ((texture_y + local_y) * page_size + slot.x) * bytes_per_pixel;
-		std::fill(texture_start, texture_start + sprite_padding * bytes_per_pixel, 0);
+		std::fill(texture_start, texture_start + sprite_padding * bytes_per_pixel, static_cast<unsigned char>(0));
 		std::fill(
-			texture_start + (sprite_padding + width) * bytes_per_pixel, texture_start + padded_width * bytes_per_pixel, 0
+			texture_start + (sprite_padding + width) * bytes_per_pixel, texture_start + padded_width * bytes_per_pixel,
+			static_cast<unsigned char>(0)
 		);
 		std::copy(data_start, data_start + width * bytes_per_pixel, texture_start + sprite_padding * bytes_per_pixel);
 	}
@@ -468,26 +469,4 @@ Vector<const unsigned char*> SpriteSet::GetTextures() const
 	return textures;
 }
 
-void SpriteSet::Dump(Vector<SpriteSet::SpriteData> &sprites) const
-{
-	if (first_page_index == null_index)
-		return;
-	for (
-		unsigned int shelf_index = page_pool[first_page_index].first_shelf_index;
-		shelf_index != null_index; shelf_index = shelf_pool[shelf_index].next_index
-	)
-	{
-		const unsigned int shelfY = shelf_pool[shelf_index].y;
-		for (
-			unsigned int slot_index = shelf_pool[shelf_index].first_slot_index;
-			slot_index != null_index; slot_index = slot_pool[slot_index].next_index
-		)
-		{
-			const Slot& slot = slot_pool[slot_index];
-			if (slot.allocated)
-				sprites.push_back({slot.x, shelfY, slot.width, slot.height});
-		}
-	}
-}
-
 } // namespace Rml

+ 0 - 2
Source/Core/FontEngineDefault/SpriteSet.h

@@ -69,8 +69,6 @@ public:
 	/// @return An array of pointers to each page's texture data.
 	Vector<const unsigned char*> GetTextures() const;
 
-	void Dump(std::vector<SpriteData> &sprites) const;
-
 private:
 	struct Page {
 		unsigned int previous_index, next_index;

+ 6 - 5
Tests/Source/Benchmarks/CMakeLists.txt

@@ -1,17 +1,18 @@
 set(TARGET_NAME "rmlui_benchmarks")
 
 add_executable(${TARGET_NAME}
+	BackgroundBorder.cpp
+	DataBinding.cpp
 	DataExpression.cpp
 	Element.cpp
-	BackgroundBorder.cpp
 	ElementDocument.cpp
-	Table.cpp
-	Selectors.cpp
-	main.cpp
-	DataBinding.cpp
 	Flexbox.cpp
 	FontEffect.cpp
+	FontTextureAtlas.cpp
+	Selectors.cpp
+	Table.cpp
 	WidgetTextInput.cpp
+	main.cpp
 )
 
 set_common_target_options(${TARGET_NAME})

+ 77 - 0
Tests/Source/Benchmarks/FontTextureAtlas.cpp

@@ -0,0 +1,77 @@
+#include "../Common/TestsShell.h"
+#include <RmlUi/Core/Context.h>
+#include <RmlUi/Core/Core.h>
+#include <RmlUi/Core/Element.h>
+#include <RmlUi/Core/ElementDocument.h>
+#include <RmlUi/Core/Types.h>
+#include <doctest.h>
+#include <nanobench.h>
+
+using namespace ankerl;
+using namespace Rml;
+
+// Start of the "CJK unified ideographs" Unicode block.
+static constexpr int rml_font_texture_atlas_start_codepoint = 0x4E00;
+
+static const String rml_font_texture_atlas_document = R"(
+<rml>
+<head>
+    <title>Font texture atlas benchmark</title>
+    <link type="text/rcss" href="/../Tests/Data/style.rcss"/>
+	<style>
+		body {
+			font-family: "Noto Sans JP";
+			font-size: %dpx;
+		}
+	</style>
+</head>
+<body id="body">
+</body>
+</rml>
+)";
+
+TEST_CASE("font_texture_atlas")
+{
+	Context* context = TestsShell::GetContext();
+	REQUIRE(context);
+
+	LoadFontFace("assets/NotoSansJP-Regular.ttf");
+
+	nanobench::Bench bench;
+	bench.title("Font texture atlas");
+	bench.relative(true);
+
+	for (const int font_size : {12, 16, 24, 48, 96})
+	{
+		const String rml_document = CreateString(rml_font_texture_atlas_document.c_str(), font_size);
+
+		ElementDocument *const document = context->LoadDocumentFromMemory(rml_document);
+		REQUIRE(document);
+		Element *const body = document->GetElementById("body");
+		REQUIRE(body);
+		document->Show();
+		context->Update();
+		context->Render();
+
+		for (const int glyph_count : {10, 100, 1000})
+		{
+			String benchmark_name;
+			FormatString(benchmark_name, "Size %d with %d glyphs", font_size, glyph_count);
+			bench.run(benchmark_name.c_str(), [&]() {
+				ReleaseFontResources();
+				for (int i = 0; i < glyph_count; ++i)
+				{
+					body->SetInnerRML(StringUtilities::ToUTF8(static_cast<Character>(
+						rml_font_texture_atlas_start_codepoint + i
+					)));
+					context->Update();
+					context->Render();
+				}
+			});
+		}
+
+		document->Close();
+	}
+
+	TestsShell::ShutdownShell();
+}