mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-09-21 20:06:40 +00:00
Font: make atlas uploads queue-aware on Vulkan
Goal
----
Avoid corrupting the dynamic font-atlas on Vulkan by blocking any
re-uploads until the command buffer that created / last updated the
texture has actually been submitted.
What changed
------------
* **Queue-aware textures**
* Added `queueSubmitAware` flag to `IDevice::CreateTexture*` APIs.
* `Vulkan::CTexture` now stores two booleans:
- `m_QueueSubmitAware` – opt-in per texture.
- `m_PendingQueueSubmit` – set to *true* the moment an upload
is recorded, cleared once the submit scheduler has flushed.
* `CRingCommandContext::ScheduleUpload` marks the texture as
pending (`SetPendingQueueSubmit(true)`).
* **Device-side watcher**
* `Vulkan::CDevice` keeps a
`m_TextureUploadWatcherQueue`. Each frame it checks textures that
were uploaded ≥ `NUMBER_OF_FRAMES_IN_FLIGHT` frames ago and
clears their pending flag.
* New helpers
`ScheduleTextureUploadWatch `,
`ProcessTextureUploadWatchQueue()`.
* **Font code**
* Atlas texture is now created with
`queueSubmitAware = true`.
* `CFont::UploadTextureAtlasToGPU()` early-outs when
`IsPendingQueueSubmit()` returns *true*, instead of tracking a
submit-handle or the manual `m_IsLoadingTextureToGPU` flag
(removed).
Why this is better
------------------
The logic to wait for a flush is localised inside the rendering
backend, so `CFont` only needs to ask *“is my texture busy?”*.
This removes the fragile submit-handle bookkeeping and works even if
the scheduler issues multiple submits per frame in future.
Result
------
Atlas uploads are deferred until the previous submit completes,
eliminating the intermittent glyph corruption on the Vulkan backend
while leaving GL and the dummy backend unchanged.
This commit is contained in:
@@ -26,7 +26,9 @@
|
||||
#include "ps/Profiler2.h"
|
||||
#include "ps/containers/Span.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/backend/Backend.h"
|
||||
#include "renderer/backend/IDevice.h"
|
||||
#include "renderer/backend/vulkan/Device.h"
|
||||
#include "renderer/backend/IDeviceCommandContext.h"
|
||||
#include "renderer/backend/ITexture.h"
|
||||
#include "renderer/backend/Sampler.h"
|
||||
@@ -288,7 +290,7 @@ bool CFont::ConstructTextureAtlas()
|
||||
Renderer::Backend::ITexture::Usage::TRANSFER_DST |
|
||||
Renderer::Backend::ITexture::Usage::SAMPLED,
|
||||
m_TextureFormat,
|
||||
textureSize, textureSize, defaultSamplerDesc
|
||||
textureSize, textureSize, defaultSamplerDesc, 1, 1, true
|
||||
));
|
||||
|
||||
if (!m_Texture)
|
||||
@@ -297,8 +299,6 @@ 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);
|
||||
@@ -493,10 +493,7 @@ std::optional<CVector2D> CFont::GenerateGlyphBitmap(FT_Glyph& glyph, u16 codepoi
|
||||
|
||||
void CFont::UploadTextureAtlasToGPU()
|
||||
{
|
||||
if (std::exchange(m_IsLoadingTextureToGPU, false))
|
||||
return;
|
||||
|
||||
if (!m_IsDirty)
|
||||
if (m_Texture->GetBackendTexture()->IsPendingQueueSubmit() || !m_IsDirty)
|
||||
return;
|
||||
|
||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext = g_Renderer.GetDeviceCommandContext();
|
||||
|
||||
Reference in New Issue
Block a user