#include "commons/commons_debug_text_renderer.h" #include #include "commons/commons_array.h" // IWYU pragma: keep #include "commons/commons_inline_vec.h" #include "commons/commons_minmax.h" #include "commons/commons_pipeline_cache.h" #include "commons/commons_region_alloc.h" #include "commons/commons_region_alloc_def.h" #include "commons/commons_rhi.h" #include "commons/commons_span.h" #include "commons/commons_span_def.h" #include "commons/commons_vec.h" namespace { struct draw_data { array words; int32_t originX; int32_t originY; uint32_t wordCount; uint32_t pad; array fg; array bg; }; struct debug_text_renderer { pipeline_cache_handle Pipeline; inline_vec pendingDraws; }; debug_text_renderer* manager; } // namespace void API DebugTextRenderer_Bootstrap(region_alloc&) { manager = &RegionAlloc_Alloc(g_BootstrapAlloc); rhi_texture_format colorFormat = rhi_texture_format::B8G8R8A8_sRGB; const rhi_graphics_pipeline_desc pipelineDesc { .debugName = "DebugTextRender"_s, .colorTargetFormats = { &colorFormat, 1 }, .depthFormat = rhi_texture_format::D32_Float_S8_UINT, }; manager->Pipeline = PipelineCache_Acquire(0xF3624967BC396A3C, 0x040C5CF806D5A00D, pipelineDesc); } void API DebugTextRenderer_Text(int32_t x, int32_t y, byteview text) { draw_data drawData { .originX = x, .originY = y, .wordCount = Min((text.size + 3) / 4, 68), .fg = { 1.f, 1.f, 1.f, 1.f }, }; const uint64_t numBytes = Min(text.size, uint64_t(drawData.wordCount) * 4); for (size_t i = 0; i < drawData.wordCount; ++i) { uint32_t word = 0; for (uint8_t j = 0; j < 4; ++j) { const uint32_t idx = i * 4 + j; if (idx < numBytes) word |= (uint32_t(uint8_t(text[idx])) << (8 * j)); } drawData.words[i / 4][i % 4] = word; } InlineVec_Append(manager->pendingDraws, drawData); } void API DebugTextRenderer_CmdFlush(rhi_cmdlist cmd) { if (manager->pendingDraws.size == 0) return; const uint32_t frameIndex = Rhi_GetFrameIndex(); Rhi_CmdBindGraphicsPipeline(cmd, PipelineCache_Resolve(manager->Pipeline)); for (const draw_data& drawData : manager->pendingDraws) { Rhi_SetLargeDrawConstant(cmd, Span_ByteViewPtr(&drawData)); Rhi_CmdDraw(cmd, 3, 1, 0, 0); } InlineVec_Clear(manager->pendingDraws); }