Fixes #8057 by properly initializing atlas texture.

Fixes #8057
Fixes #8184
Fixes #8345
This commit is contained in:
Vladislav Belov 2025-09-17 14:31:16 +02:00
parent 3eca24ed11
commit e8a5103f8c
No known key found for this signature in database
GPG key ID: 353545E45DB9CCB3
12 changed files with 45 additions and 32 deletions

View file

@ -180,7 +180,7 @@ bool CFont::SetFontParams(const std::string& fontName, float size, float strokeW
FT_Stroker_Set(m_Stroker.get(), FloatToF26Dot6(m_StrokeWidth), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
}
if (!ConstructTextureAtlas())
if (!ConstructAtlasTexture())
{
LOGERROR("Failed to create font texture atlas %s", fontName);
return false;
@ -262,7 +262,7 @@ Renderer::Backend::Sampler::Desc CFont::ChooseTextureFormatAndSampler()
return defaultSamplerDesc;
}
bool CFont::ConstructTextureAtlas()
bool CFont::ConstructAtlasTexture()
{
Renderer::Backend::IDevice* backendDevice = g_Renderer.GetDeviceCommandContext()->GetDevice();
@ -287,7 +287,7 @@ bool CFont::ConstructTextureAtlas()
m_Texture = g_Renderer.GetTextureManager().WrapBackendTexture(backendDevice->CreateTexture2D(
("Font Texture " + m_FontName).c_str(),
Renderer::Backend::ITexture::Usage::TRANSFER_DST |
Renderer::Backend::ITexture::Usage::SAMPLED,
Renderer::Backend::ITexture::Usage::SAMPLED,
m_TextureFormat,
textureSize, textureSize, defaultSamplerDesc
));
@ -298,18 +298,27 @@ bool CFont::ConstructTextureAtlas()
return false;
}
m_IsLoadingTextureToGPU = true;
// Initialise texture with transparency, for the areas we don't
// overwrite with uploading later.
m_TexData = std::make_unique<u8[]>(m_AtlasSize);
std::fill_n(m_TexData.get(), m_AtlasSize, 0x00);
g_Renderer.GetDeviceCommandContext()->UploadTexture(
m_IsTextureInitialized = false;
return true;
}
void CFont::InitalizeAtlasTextureIfNeeded(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (m_IsTextureInitialized)
return;
deviceCommandContext->UploadTexture(
m_Texture->GetBackendTexture(), m_TextureFormat,
m_TexData.get(), m_AtlasSize);
return true;
m_IsTextureInitialized = true;
}
const CFont::GlyphData* CFont::GetGlyph(u16 codepoint)
@ -492,24 +501,16 @@ std::optional<CVector2D> CFont::GenerateGlyphBitmap(FT_Glyph& glyph, u16 codepoi
return newOffset;
}
void CFont::UploadTextureAtlasToGPU()
void CFont::UploadAtlasTextureToGPU(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (std::exchange(m_IsLoadingTextureToGPU, false))
return;
if (!m_IsDirty)
return;
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = g_Renderer.GetDeviceCommandContext();
PROFILE2("Loading font texture");
GPU_SCOPED_LABEL(deviceCommandContext, "Loading font texture");
deviceCommandContext->UploadTextureRegion(
deviceCommandContext->UploadTexture(
m_Texture->GetBackendTexture(),
m_TextureFormat,
m_TexData.get(),
m_AtlasSize,
0, 0, m_AtlasWidth, m_AtlasHeight
m_AtlasSize
);
m_IsDirty = false;

View file

@ -38,6 +38,7 @@
#include <vector>
class CVector2D;
namespace Renderer::Backend { class IDeviceCommandContext; }
namespace Renderer::Backend::Sampler { struct Desc; }
/**
@ -110,7 +111,10 @@ public:
}
CTexturePtr GetTexture() const { return m_Texture; }
void UploadTextureAtlasToGPU();
void InitalizeAtlasTextureIfNeeded(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void UploadAtlasTextureToGPU(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
const GlyphData* GetGlyph(u16 i);
private:
@ -140,7 +144,7 @@ private:
std::optional<CVector2D> GenerateGlyphBitmap(FT_Glyph& glyph, u16 codepoint, FT_Render_Mode renderMode, CVector2D offset, const float baselineInAtlas);
const GlyphData* ExtractAndGenerateGlyph(u16 codepoint);
bool ConstructTextureAtlas();
bool ConstructAtlasTexture();
Renderer::Backend::Sampler::Desc ChooseTextureFormatAndSampler();
CTexturePtr m_Texture;
@ -166,7 +170,7 @@ private:
int m_AtlasPadding;
bool m_IsDirty{false};
bool m_IsLoadingTextureToGPU{false};
bool m_IsTextureInitialized{false};
float m_StrokeWidth{0.0f};
float m_Scale{1.0f};

View file

@ -28,6 +28,7 @@
#include "ps/CStrInternStatic.h"
#include "ps/ConfigDB.h"
#include "ps/Filesystem.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include <algorithm>
#include <cmath>
@ -230,13 +231,16 @@ std::shared_ptr<CFont> CFontManager::LoadFont(CStrIntern fontName, CStrIntern lo
return font;
}
void CFontManager::UploadTexturesAtlasToGPU()
void CFontManager::UploadAtlasTexturesToGPU(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
PROFILE2("Loading font textures");
GPU_SCOPED_LABEL(deviceCommandContext, "Loading font textures");
for (auto& [fontName, fontPtr] : m_Fonts)
{
if (!fontPtr)
continue;
fontPtr->UploadTextureAtlasToGPU();
fontPtr->UploadAtlasTextureToGPU(deviceCommandContext);
}
}

View file

@ -30,6 +30,8 @@
class CFont;
struct FT_LibraryRec_;
namespace Renderer::Backend { class IDeviceCommandContext; }
/**
* Font manager: loads and caches bitmap fonts.
*/
@ -41,7 +43,8 @@ public:
NONCOPYABLE(CFontManager);
std::shared_ptr<CFont> LoadFont(CStrIntern fontName, CStrIntern locale);
void UploadTexturesAtlasToGPU();
void UploadAtlasTexturesToGPU(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
private:
static void ftLibraryDeleter(FT_Library library)

View file

@ -214,7 +214,7 @@ void CTextRenderer::Render(
std::vector<CVector2D> uvs;
const bool debugFontBox{g_ConfigDB.Get("fonts.debugbox", false)};
const std::string debugFontBoxColor{ g_ConfigDB.Get("fonts.debugboxcolor", std::string{"128 0 128"})};
const std::string debugFontBoxColor{g_ConfigDB.Get("fonts.debugboxcolor", std::string{"128 0 128"})};
CColor debugBoxColor;
debugBoxColor.ParseString(debugFontBoxColor.c_str());
@ -248,6 +248,7 @@ void CTextRenderer::Render(
if (lastTexture != batch.font->GetTexture().get())
{
batch.font->InitalizeAtlasTextureIfNeeded(deviceCommandContext);
lastTexture = batch.font->GetTexture().get();
lastTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
deviceCommandContext->SetTexture(texBindingSlot, lastTexture->GetBackendTexture());

View file

@ -662,7 +662,7 @@ void CRenderer::RenderFrame2D(const bool renderGUI, const bool renderLogger)
g_ProfileViewer.RenderProfile(canvas);
}
this->GetFontManager().UploadTexturesAtlasToGPU();
GetFontManager().UploadAtlasTexturesToGPU(m->deviceCommandContext.get());
}
void CRenderer::RenderScreenShot(const bool needsPresent)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2023 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify