Mission Vishwakarma Download Roadmap Pricing

User Interface

We follow the standard ribbon interface for UI. Further, supporting all indian scheduled languages is must. This will als enable us to support international languages in future. Please refer below actual code files for user interface design specifications. We have baseline strings say N numbers in English. Each string can have a corresponding language translation or if the language translation is empty string, than the corresponding english text shall be followed. All translations are stored in UserInterface-Text.h file.

Supporting all Indian languages is mostly a data organization + text shaping problem, not a rendering problem. Renderer will just draw glyphs; the system around it decides which string to show.

Translation Document

  1// Copyright (c) 2026-Present : Ram Shanker: All rights reserved.
  2#pragma once
  3
  4enum class UILanguage : uint8_t
  5{
  6    English = 0,
  7
  8    // 22 Indian scheduled languages
  9    /* Here is the list of the given languages arranged in descending order of the number of speakers.
 10    2011 Census of India data for total speakers, including both native/mother tongue and second-language speakers where reported,
 11    as this is the most comprehensive official source available). */
 12
 13    Hindi, // ~528โ€“691 million total speakers; ~43.63% of India's population as native speakers alone)
 14    Bengali, // ~97โ€“107 million
 15    Marathi, // ~83โ€“99 million
 16    Telugu, // ~81โ€“94 million
 17    Tamil, // ~69โ€“76 million
 18    Gujarati, // ~55โ€“60 million
 19    Urdu, // ~50โ€“63 million
 20    Kannada, // ~43โ€“58 million
 21    Odia, // ~37โ€“42 million
 22    Malayalam, // ~34โ€“35 million
 23    Punjabi, // ~33โ€“36 million
 24    Assamese, // ~15โ€“23 million
 25    Maithili, // ~13โ€“14 million, based on ~1.12% share)
 26    Santali, // ~7.3โ€“7.7 million
 27    Kashmiri, // ~6.8โ€“7 million
 28    Nepali, // ~2.9โ€“3 million
 29    Sindhi, // ~2.7โ€“3 million
 30    Dogri, // ~2.6โ€“2.8 million
 31    Konkani, // ~2.2โ€“2.6 million
 32    Manipuri, // (Meitei) ~1.7โ€“2 million
 33    Bodo, // ~1.4โ€“1.6 million
 34    Sanskrit, // ~25,000 native speakers; higher if including those reporting knowledge, but still by far the smallest)
 35
 36    // Major global engineering languages. Population number by Grok citing 
 37    ChineseSimplified, // Both Chinese combined ~1.18โ€“1.20 billion total speakers (mostly native)
 38    ChineseTraditional, //(Mandarin Chinese)
 39    Spanish, // ~558โ€“560 million
 40    Portuguese, // ~264โ€“270 million
 41    Russian, // ~253โ€“260 million
 42    French, // ~312โ€“330 million (some sources place it slightly above or near Arabic depending on L2 counting)
 43    Arabic, // ~335 million (Modern Standard Arabic + varieties; widely used in engineering contexts across the Middle East)
 44    Indonesian, // ~200โ€“255 million
 45    German, // ~130โ€“134 million
 46    Japanese, // ~125โ€“126 million. Covers all of Katakana , Kanji and Hiragana symbols within same fonts.
 47    Vietnamese, // ~85โ€“97 million
 48    Turkish, // ~80โ€“90 million
 49    Persian, // (Farsi) โ€” ~70โ€“82 million. Farsi - Iran engineering market
 50    Korean, // ~80โ€“85 million
 51    Italian, // ~65โ€“90 million
 52    Thai, // ~60โ€“70 million
 53    Polish, // ~45โ€“50 million
 54    Ukrainian, // ~35โ€“45 million
 55    Dutch, // ~25โ€“30 million
 56    Filipino, // (Tagalog) ~80โ€“90 million total (native ~25โ€“30 million + significant L2 in Philippines)
 57    Swedish, // ~10โ€“15 million
 58    Czech, // ~10โ€“12 million
 59    Hungarian, // ~12โ€“14 million
 60
 61    COUNT
 62};
 63
 64/*
 65ChatGPT analysis of population coverage by above 46 languages:
 66
 67| Metric                         | Result     |
 68| ------------------------------ | ---------- |
 69| World population coverage      | **90โ€“94%** |
 70| Engineering workforce coverage | **97โ€“99%** |
 71| India coverage                 | **~99%**   |
 72| Europe coverage                | **~95%**   |
 73| Americas coverage              | **~95%**   |
 74
 75All these 46 languages translate to 13 unique scripts. Unicode handles all of them well.
 76
 77| Script        | Languages                             |
 78| ------------- | ------------------------------------- |
 79| Latin         | English, German, French, Spanish, etc |
 80| Devanagari    | Hindi, Marathi, Nepali etc            |
 81| Bengali       | Bengali, Assamese                     |
 82| Gurmukhi      | Punjabi                               |
 83| Gujarati      | Gujarati                              |
 84| Odia          | Odia                                  |
 85| Tamil         | Tamil                                 |
 86| Telugu        | Telugu                                |
 87| Kannada       | Kannada                               |
 88| Malayalam     | Malayalam                             |
 89| Arabic script | Urdu, Arabic, Persian, Kashmiri       |
 90| Chinese Han   | Chinese + Japanese Kanji              |
 91| Japanese kana | Hiragana/Katakana                     |
 92| Hangul        | Korean                                |
 93| Thai          | Thai                                  |
 94
 95Professional CAD software language coverage (As per ChatGPT).
 96| Software   | Languages |
 97| ---------- | --------- |
 98| AutoCAD    | ~15       |
 99| SolidWorks | ~13       |
100| Fusion360  | ~10       |
101| CATIA      | ~8        |
102All softwares listed below are copy right of respective software companies.
103
104HENCE OUR LANGUAGE LIST IS FROZEN ! ;)
105
106Estimated size overhead of bundling all the fonts:
107
108| Font                         | Typical Size |
109| ---------------------------- | ------------ |
110| Noto Sans (Latin + extended) | ~2 MB        |
111| Noto Sans Devanagari         | ~1.5 MB      |
112| Noto Sans Bengali            | ~1.3 MB      |
113| Noto Sans Gurmukhi           | ~0.9 MB      |
114| Noto Sans Gujarati           | ~1.0 MB      |
115| Noto Sans Oriya (Odia)       | ~1.1 MB      |
116| Noto Sans Tamil              | ~0.9 MB      |
117| Noto Sans Telugu             | ~1.2 MB      |
118| Noto Sans Kannada            | ~1.2 MB      |
119| Noto Sans Malayalam          | ~1.4 MB      |
120| Noto Sans Arabic             | ~1.2 MB      |
121| Noto Sans Thai               | ~0.7 MB      |
122
123Subtotal (non-CJK): โ‰ˆ 14โ€“15 MB
124
125| Font                                   | Approx Size |
126| -------------------------------------- | ----------- |
127| Noto Sans CJK SC (Simplified Chinese)  | ~16โ€“18 MB   |
128| Noto Sans CJK TC (Traditional Chinese) | ~16โ€“18 MB   |
129| Noto Sans CJK JP (Japanese)            | ~16โ€“18 MB   |
130| Noto Sans CJK KR (Korean)              | ~16โ€“18 MB   |
131
132CJK 3 variants (SC + JP + KR): โ‰ˆ 48โ€“54 MB
133
134Total: โ‰ˆ 65 MB , ~60% Compression expected in Installer. โ‰ˆ 40 MB. Acceptable.
135
136Runtime: Entire font files will not be loaded at runtime.
137They will be loaded on demand to minimize memory footprint.
138
139*/

User Interface Design Document and Implementation!

 1// Copyright (c) 2026-Present : Ram Shanker: All rights reserved.
 2#pragma once
 3
 4#define WIN32_LEAN_AND_MEAN
 5#define NOMINMAX   //
 6#include <windows.h>   // MUST be before d3d12.h
 7#include <d3d12.h>
 8#include <d3dx12.h>
 9#include <dxgi1_6.h>
10#include <wrl.h>
11#include <vector>
12#include <unordered_map>
13#include <iostream>
14#include <atomic>
15
16#include "ConstantsApplication.h"
17#include "UserInterface.h" // It also includes "UserInterface-TextTranslations.h"
18
19// Do not #include "เคตเคฟเคถเฅเคตเค•เคฐเฅเคฎเคพ.h" otherwise it will lead to circular dependency error. Declare this struct exist.
20struct SingleUIWindow; // Add this forward declaration:
21
22using Microsoft::WRL::ComPtr;
23
24struct DX12ResourcesUI { // GPU resources
25    ComPtr<ID3D12Resource> uiAtlasTexture; // 1024ร—1024 or 2048ร—2048 RGBA (or R8 for alpha-only)
26    ComPtr<ID3D12Resource> uiVertexBuffer; // Dynamic upload buffer for vertices
27    ComPtr<ID3D12Resource> uiIndexBuffer;  // Dynamic upload buffer for indices
28
29    UINT8* pVertexDataBegin = nullptr; // Mapped pointer for immediate writing
30    UINT8* pIndexDataBegin = nullptr;
31    UINT8* pOrthoDataBegin = nullptr;
32
33    ID3D12Resource* iconAtlas; // Required ?
34    ComPtr<ID3D12PipelineState> uiPSO;
35    ComPtr<ID3D12RootSignature> uiRootSignature;
36    ComPtr<ID3D12Resource> uiOrthoConstantBuffer;
37    ComPtr<ID3D12DescriptorHeap> srvHeap;
38    ComPtr<ID3D12DescriptorHeap> samplerHeap;
39
40    uint32_t maxVertices = 65536;
41    uint32_t maxIndices = 65536 * 3;
42};
43
44struct UIDrawContext { // Draw context
45    UIVertex* vertexPtr;
46    uint16_t* indexPtr;
47    uint32_t vertexCount, indexCount;
48};
49
50// DirectX12 Immediate Mode UI System (Phase 4A). Tab Bar Rendering Only
51// External interfaces of User Interface sub module of the code.
52void InitUIResources( DX12ResourcesUI& uiRes, ID3D12Device* device);
53void CleanupUIResources( DX12ResourcesUI& uiRes);
54
55void PushRect(UIDrawContext& ctx, float x, float y, float w, float h, uint32_t color, DX12ResourcesUI& uiRes);
56void PushText(UIDrawContext& ctx, float x, float y, const char* text, uint32_t color, DX12ResourcesUI& uiRes);
57void RenderUIOverlay( SingleUIWindow& window, ID3D12GraphicsCommandList* cmdList,
58    DX12ResourcesUI& uiRes, float monitorDPI, const UIInput& input);
  1// Copyright (c) 2026-Present : Ram Shanker: All rights reserved.
  2
  3#include "UserInterface-DirectX12.h"
  4#include <d3dcompiler.h>
  5#include "FontManager.h"
  6#include <MemoryManagerGPU-DirectX12.h>
  7#include "เคตเคฟเคถเฅเคตเค•เคฐเฅเคฎเคพ.h"
  8extern เคถเค‚เค•เคฐ gpu;
  9extern std::atomic<uint16_t*> publishedTabIndexes;
 10extern std::atomic<uint16_t>  publishedTabCount;
 11std::atomic<uint32_t> actionWriteIndex;
 12std::string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
 13std::atomic<uint64_t> atlasFence = 0;
 14
 15// Shader compilation helper
 16static void CompileShader( const char* code, const char* entry, const char* target, UINT flags,
 17    ComPtr<ID3DBlob>& outBlob) {
 18
 19    ComPtr<ID3DBlob> errorBlob;
 20    HRESULT hr = D3DCompile( code, strlen(code), nullptr, nullptr, nullptr, entry, target, flags, 0,
 21        &outBlob, &errorBlob);
 22    if (FAILED(hr)) {
 23        if (errorBlob) { std::cerr << (char*)errorBlob->GetBufferPointer() << std::endl; }
 24        ThrowIfFailed(hr);
 25    }
 26}
 27
 28bool SubmitTextureUpload(const TextureUploadDesc& desc,
 29    ComPtr<ID3D12Resource>* outTex,  std::atomic<uint64_t>* fenceOut) {
 30
 31    uint32_t index = gUploadQueue.writeIndex.fetch_add(1, std::memory_order_relaxed);
 32    UploadRequest& req = gUploadQueue.requests[index % MAX_UPLOAD_REQUESTS];
 33
 34    req.type = UploadType::Texture2D;
 35    req.texture = desc;
 36    req.outResource = outTex;
 37    req.completionFence = fenceOut;
 38
 39    return true;
 40}
 41
 42void InitUIResources( DX12ResourcesUI& uiRes, ID3D12Device* device) {
 43    if (!InitFontSystem()) { // FONT system initialization (CPU-side)
 44        std::cerr << "Font system initilization failed failed\n";
 45        return;
 46    }
 47
 48    // Root signature
 49    CD3DX12_DESCRIPTOR_RANGE1 ranges[2]; // Descriptor ranges
 50
 51    // Range 0: SRV (t0)  โ†’ from srvHeap // 1: 1 Texture, 0: register t0 = atlas
 52    ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_NONE);
 53    // Range 1: SAMPLER (s0) โ†’ from samplerHeap // 1: 1 Sampler, 0: register s0 = sampler
 54    ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_NONE);
 55
 56    CD3DX12_ROOT_PARAMETER1 rootParams[3];
 57    rootParams[0].InitAsConstantBufferView(0, 0, D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
 58        D3D12_SHADER_VISIBILITY_VERTEX);// b0 - Ortho constant buffer (vertex shader)
 59
 60    // Root Parameter 1: Descriptor Table containing only the SRV
 61    rootParams[1].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL);
 62
 63    // Root Parameter 2: Descriptor Table containing only the SAMPLER
 64    rootParams[2].InitAsDescriptorTable(1, &ranges[1],
 65        D3D12_SHADER_VISIBILITY_PIXEL);
 66
 67    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootDesc;
 68    rootDesc.Init_1_1(_countof(rootParams), rootParams, 0, nullptr,
 69        D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
 70
 71    ComPtr<ID3DBlob> signature;
 72    ComPtr<ID3DBlob> errorBlob;
 73
 74    HRESULT hr = D3DX12SerializeVersionedRootSignature(&rootDesc,
 75        D3D_ROOT_SIGNATURE_VERSION_1_1, &signature, &errorBlob);
 76    if (FAILED(hr)) {
 77        if (errorBlob)
 78            std::cerr << "Root Signature Serialization Failed:\n"
 79            << (char*)errorBlob->GetBufferPointer() << std::endl;
 80        ThrowIfFailed(hr); // will print the real error
 81    }
 82
 83    ThrowIfFailed(device->CreateRootSignature(0, signature->GetBufferPointer(),
 84        signature->GetBufferSize(), IID_PPV_ARGS(&uiRes.uiRootSignature)));
 85
 86    // Create SRV descriptor heap (1 texture)
 87    D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
 88    heapDesc.NumDescriptors = 1;
 89    heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
 90    heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
 91    ThrowIfFailed(device->CreateDescriptorHeap( &heapDesc, IID_PPV_ARGS(&uiRes.srvHeap) ));
 92
 93    // Create SAMPLER descriptor heap (shader-visible)
 94    D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {};
 95    samplerHeapDesc.NumDescriptors = 1;
 96    samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
 97    samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
 98    ThrowIfFailed(device->CreateDescriptorHeap(&samplerHeapDesc,
 99        IID_PPV_ARGS(&uiRes.samplerHeap)));
100
101    // Create the actual sampler (Point sampling is perfect for UI atlas)
102    D3D12_SAMPLER_DESC samplerDesc = {};
103    samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;   // sharp UI text
104    samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
105    samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
106    samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
107    samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
108    samplerDesc.MinLOD = 0;
109    samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
110
111    device->CreateSampler(&samplerDesc,
112        uiRes.samplerHeap->GetCPUDescriptorHandleForHeapStart());
113
114    // Shaders
115
116#if defined(_DEBUG)
117    UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
118#else
119    UINT compileFlags = 0;
120#endif
121
122    static const char* vsCode = R"(
123cbuffer OrthoConstantBuffer : register(b0) {
124    float4x4 ortho;
125};
126
127struct VSInput {
128    float2 position : POSITION;
129    float2 uv       : TEXCOORD0;
130    uint   color    : COLOR0;
131};
132
133struct PSInput {
134    float4 position : SV_POSITION;
135    float2 uv       : TEXCOORD0;
136    uint   color    : COLOR0;
137};
138
139PSInput VSMain(VSInput input) {
140    PSInput output;
141    float4 pos = float4(input.position,0,1);
142    output.position = mul(pos,ortho);
143    output.uv = input.uv;
144    output.color = input.color;
145    return output;
146}
147)";
148
149    static const char* psCode = R"(
150struct PSInput {
151    float4 position : SV_POSITION;
152    float2 uv       : TEXCOORD0;
153    uint   color    : COLOR0;
154};
155
156Texture2D atlas : register(t0);
157SamplerState samp : register(s0);
158
159float4 PSMain(PSInput input) : SV_TARGET {
160    float4 tex = atlas.Sample(samp, input.uv);
161    float r = ((input.color >> 0) & 0xFF) / 255.0;
162    float g = ((input.color >> 8) & 0xFF) / 255.0;
163    float b = ((input.color >> 16) & 0xFF) / 255.0;
164    float a = ((input.color >> 24) & 0xFF) / 255.0;
165    return float4(r, g, b, a) * tex;
166}
167)";
168
169    ComPtr<ID3DBlob> vsBlob;
170    ComPtr<ID3DBlob> psBlob;
171    CompileShader(vsCode, "VSMain", "vs_5_0", compileFlags, vsBlob);
172    CompileShader(psCode, "PSMain", "ps_5_0", compileFlags, psBlob);
173    // Input layout
174
175    D3D12_INPUT_ELEMENT_DESC layout[] = {
176        { "POSITION",0,DXGI_FORMAT_R32G32_FLOAT,0,0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 },
177        { "TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 },
178        { "COLOR",0,DXGI_FORMAT_R32_UINT,0,16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 }
179    };
180
181    // PSO
182    D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
183    psoDesc.InputLayout = { layout,_countof(layout) };
184    psoDesc.pRootSignature = uiRes.uiRootSignature.Get();
185    psoDesc.VS = CD3DX12_SHADER_BYTECODE(vsBlob.Get());
186    psoDesc.PS = CD3DX12_SHADER_BYTECODE(psBlob.Get());
187    psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
188    psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
189    psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
190    psoDesc.BlendState.RenderTarget[0].BlendEnable = TRUE;
191    psoDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
192    psoDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
193    psoDesc.DepthStencilState.DepthEnable = FALSE;
194    psoDesc.SampleMask = UINT_MAX;
195    psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
196    psoDesc.NumRenderTargets = 1;
197    psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
198    psoDesc.SampleDesc.Count = 1;
199
200    ThrowIfFailed( device->CreateGraphicsPipelineState( &psoDesc, IID_PPV_ARGS(&uiRes.uiPSO)));
201
202    // Vertex buffer
203    auto uploadHeap = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
204
205    auto vbDesc = CD3DX12_RESOURCE_DESC::Buffer( uiRes.maxVertices * sizeof(UIVertex));
206    ThrowIfFailed( device->CreateCommittedResource( &uploadHeap, D3D12_HEAP_FLAG_NONE, &vbDesc,
207            D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uiRes.uiVertexBuffer)));
208
209    auto ibDesc = CD3DX12_RESOURCE_DESC::Buffer( uiRes.maxIndices * sizeof(uint16_t));
210    ThrowIfFailed( device->CreateCommittedResource( &uploadHeap, D3D12_HEAP_FLAG_NONE, &ibDesc,
211            D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uiRes.uiIndexBuffer)));
212
213    auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(256);
214    ThrowIfFailed( device->CreateCommittedResource( &uploadHeap, D3D12_HEAP_FLAG_NONE, &cbDesc,
215            D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uiRes.uiOrthoConstantBuffer)));
216
217    CD3DX12_RANGE readRange(0, 0);
218    uiRes.uiVertexBuffer->Map( 0, &readRange, reinterpret_cast<void**>(&uiRes.pVertexDataBegin));
219    uiRes.uiIndexBuffer->Map(  0, &readRange, reinterpret_cast<void**>(&uiRes.pIndexDataBegin));
220    uiRes.uiOrthoConstantBuffer->Map( 0, &readRange, reinterpret_cast<void**>(&uiRes.pOrthoDataBegin));
221    std::wcout << L"UI Resources Initialized (Phase 4A)\n";
222
223    AtlasBitmap atlas = BuildFontAtlas();// BUILD ATLAS ON CPU
224
225    TextureUploadDesc desc = {};
226    desc.width = atlas.width;
227    desc.height = atlas.height;
228    desc.format = DXGI_FORMAT_R8_UNORM;
229    desc.pixels = atlas.pixels.data();
230    desc.rowPitch = atlas.width;
231
232    SubmitTextureUpload(desc, &uiRes.uiAtlasTexture, &atlasFence);// Enqueue the upload through upload queue
233    // RESERVED FENCE VALUE FOR THIS UPLOAD (this is the key change)
234    // The copy thread MUST eventually signal exactly this value.
235    uint64_t atlasReadyFence = gpu.copyFenceValue.fetch_add(1, std::memory_order_relaxed);
236    // Tell everyone (including the render thread) what fence value to wait for
237    atlasFence.store(atlasReadyFence, std::memory_order_release);
238    // CPU-blocking wait until Copy Queue has processed this upload
239    if (gpu.copyFence->GetCompletedValue() < atlasReadyFence) {
240        ThrowIfFailed(gpu.copyFence->SetEventOnCompletion(atlasReadyFence, gpu.copyFenceEvent));
241        WaitForSingleObject(gpu.copyFenceEvent, INFINITE);   // CPU blocks here
242    }
243
244    // Now the texture is in DEFAULT heap โ†’ safe to create SRV
245    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
246    srvDesc.Format = DXGI_FORMAT_R8_UNORM;
247    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
248    srvDesc.Texture2D.MipLevels = 1;
249    srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
250
251    device->CreateShaderResourceView(uiRes.uiAtlasTexture.Get(), &srvDesc,
252        uiRes.srvHeap->GetCPUDescriptorHandleForHeapStart());
253
254    std::wcout << L"UI Atlas uploaded and SRV created (fence = " << atlasReadyFence << L")\n";
255}
256
257// Cleanup
258void CleanupUIResources(DX12ResourcesUI& uiRes) {
259    if (uiRes.uiVertexBuffer) uiRes.uiVertexBuffer->Unmap(0, nullptr);
260    if (uiRes.uiIndexBuffer) uiRes.uiIndexBuffer->Unmap(0, nullptr);
261    if (uiRes.uiOrthoConstantBuffer) uiRes.uiOrthoConstantBuffer->Unmap(0, nullptr);
262
263    uiRes = {};
264}
265
266// PushRect
267void PushRect( UIDrawContext& ctx, float x, float y, float w, float h,
268    uint32_t color, DX12ResourcesUI& uiRes) {
269    if (ctx.vertexCount + 4 > uiRes.maxVertices) return;
270    if (ctx.indexCount + 6 > uiRes.maxIndices) return;
271
272    uint16_t base = ctx.vertexCount;
273
274    ctx.vertexPtr[0] = { x,y,0,0,color };
275    ctx.vertexPtr[1] = { x + w,y,0,0,color };
276    ctx.vertexPtr[2] = { x + w,y + h,0,0,color };
277    ctx.vertexPtr[3] = { x,y + h,0,0,color };
278
279    ctx.indexPtr[0] = base + 0;
280    ctx.indexPtr[1] = base + 1;
281    ctx.indexPtr[2] = base + 2;
282    ctx.indexPtr[3] = base + 0;
283    ctx.indexPtr[4] = base + 2;
284    ctx.indexPtr[5] = base + 3;
285
286    ctx.vertexPtr += 4;
287    ctx.indexPtr += 6;
288    ctx.vertexCount += 4;
289    ctx.indexCount += 6;
290}
291
292// Returns true if clicked this frame
293bool PushInteractiveRect(UIDrawContext& ctx, float x, float y, float w, float h, uint32_t baseColor,
294    uint32_t id, const UIInput& input, DX12ResourcesUI& uiRes, bool enabled = true) {
295    uint32_t color = baseColor;
296
297    bool hovered = enabled && (input.mouseX >= x && input.mouseX < x + w &&
298        input.mouseY >= y && input.mouseY < y + h);
299
300    if (hovered) color = 0xFF555555; // hover tint (TODO: theme-aware)
301    if (hovered && input.leftButtonDown) color = 0xFF333333; // pressed tint
302    if (!enabled) color = 0xFF1E1E1E; // If disabled, force a darker/grayer base color
303    
304    PushRect(ctx, x, y, w, h, color, uiRes);
305
306    if (!enabled) return false;// Disabled controls do NOT respond to clicks
307    if (hovered && input.leftButtonPressedThisFrame) {
308        return true;
309    }
310    return false;
311}
312
313void PushText(UIDrawContext& ctx, float x, float y, const char* text, uint32_t color, DX12ResourcesUI& uiRes)
314{
315    float cursorX = x;
316
317    for (const char* p = text; *p; ++p)
318    {
319        char c = *p;
320        if (glyphLookup.find(c) == glyphLookup.end()) continue;
321
322        const Glyph& g = glyphLookup[c];
323
324        float xpos = cursorX + g.bearingX;
325        float ypos = y - g.bearingY;
326        float w = (float)g.width;
327        float h = (float)g.height;
328        uint16_t base = ctx.vertexCount;
329        
330        // Add 4 vertices
331        uint32_t vidx = ctx.vertexCount;
332        ctx.vertexPtr[vidx + 0] = { xpos,     ypos,     g.uvMinX, g.uvMinY, color };
333        ctx.vertexPtr[vidx + 1] = { xpos + w, ypos,     g.uvMaxX, g.uvMinY, color };
334        ctx.vertexPtr[vidx + 2] = { xpos + w, ypos + h, g.uvMaxX, g.uvMaxY, color };
335        ctx.vertexPtr[vidx + 3] = { xpos,     ypos + h, g.uvMinX, g.uvMaxY, color };
336
337        // Add 6 indices
338        uint32_t iidx = ctx.indexCount;
339        ctx.indexPtr[iidx + 0] = vidx + 0;
340        ctx.indexPtr[iidx + 1] = vidx + 1;
341        ctx.indexPtr[iidx + 2] = vidx + 2;
342        ctx.indexPtr[iidx + 3] = vidx + 0;
343        ctx.indexPtr[iidx + 4] = vidx + 2;
344        ctx.indexPtr[iidx + 5] = vidx + 3;
345
346        ctx.vertexPtr += 4;
347        ctx.indexPtr += 6;
348        ctx.vertexCount += 4;
349        ctx.indexCount += 6;
350
351        cursorX += g.advanceX;
352    }
353}
354
355// Convenience for tabs (fixed width for now)
356bool PushTab(UIDrawContext& ctx, float x, float w, float h, uint16_t tabID, bool isActive,
357    const UIInput& input, DX12ResourcesUI& uiRes) {
358    
359    uint32_t color = isActive ? COLOR_UI_TAB_ACTIVE : COLOR_UI_TAB_INACTIVE;
360    uint32_t actionID = 0x10000000u | tabID;   // high bit = tab family
361
362    if (PushInteractiveRect(ctx, x, 0, w, h, color, actionID, input, uiRes)) {
363        // Optional immediate feedback (UI thread)
364        // window.activeTabIndex = tabID;   // you can still do it here if you want instant visual
365        return true;
366    }
367    return false;
368}
369
370// This function renders the list of tabs, all top menu buttons (with dropdowns if required),
371// side favourite / frequent buttons bars, right side property window, bottom status bar.
372// This is also responsible for all relevant DirectX12 configurations required for rendering User Interface.
373void RenderUIOverlay(SingleUIWindow& window, ID3D12GraphicsCommandList* cmd, DX12ResourcesUI& uiRes,
374    float monitorDPI, const UIInput& input) {
375    
376    if (!cmd) return; //Defensive check.
377
378    cmd->SetPipelineState(uiRes.uiPSO.Get());
379    cmd->SetGraphicsRootSignature(uiRes.uiRootSignature.Get());
380
381    // Bind descriptor heap
382    ID3D12DescriptorHeap* heaps[] = { uiRes.srvHeap.Get(), uiRes.samplerHeap.Get() };
383    cmd->SetDescriptorHeaps(_countof(heaps), heaps);
384
385    // Bind the descriptor table (which contains t0 + s0)    
386    // Root Parameter 1 = SRV table// must match rootParams[1]
387    cmd->SetGraphicsRootDescriptorTable(1, uiRes.srvHeap->GetGPUDescriptorHandleForHeapStart());
388    // Root Parameter 2 = Sampler table
389    cmd->SetGraphicsRootDescriptorTable(2, uiRes.samplerHeap->GetGPUDescriptorHandleForHeapStart());
390    // Bind ortho constant buffer (still root parameter 0)
391    cmd->SetGraphicsRootConstantBufferView(0, uiRes.uiOrthoConstantBuffer->GetGPUVirtualAddress());
392
393    float W = (float)window.dx.WindowWidth;
394    float H = (float)window.dx.WindowHeight;
395    float* ortho = (float*)uiRes.pOrthoDataBegin;
396
397    ortho[0] = 2 / W; ortho[1] = 0;   ortho[2] = 0; ortho[3] = -1;
398    ortho[4] = 0;   ortho[5] = -2 / H; ortho[6] = 0; ortho[7] = 1;
399    ortho[8] = 0;   ortho[9] = 0;   ortho[10] = 1; ortho[11] = 0;
400    ortho[12] = 0;  ortho[13] = 0;  ortho[14] = 0; ortho[15] = 1;
401
402    cmd->SetGraphicsRootConstantBufferView( 0, uiRes.uiOrthoConstantBuffer->GetGPUVirtualAddress());
403
404    UIDrawContext ctx;
405    ctx.vertexPtr = reinterpret_cast<UIVertex*>(uiRes.pVertexDataBegin);
406    ctx.indexPtr = reinterpret_cast<uint16_t*>(uiRes.pIndexDataBegin);
407    ctx.vertexCount = 0;
408    ctx.indexCount = 0;
409    float pixelsPerMM = monitorDPI / 25.4f;
410    float buttonWidthPx = UI_BUTTON_WIDTH_MM * pixelsPerMM;
411    float tabBarHeight = UI_TAB_BAR_HEIGHT_MM * pixelsPerMM;
412    float ribbonY = tabBarHeight + UI_DIVIDER_WIDTH_PX;   // โ† only one declaration
413
414    // ENGINEERING / PROJECT TABs
415    float tabWidth = 120.0f;
416    float currentX = 0.0f;
417
418    uint16_t tabCount = publishedTabCount.load(std::memory_order_acquire);
419    uint16_t* tabList = publishedTabIndexes.load(std::memory_order_acquire);
420
421    for (uint16_t i = 0; i < tabCount; i++) {
422        uint16_t tabID = tabList[i];
423        bool active = (window.activeTabIndex == tabID);
424        if (PushTab(ctx, currentX, tabWidth, tabBarHeight, tabID, active, input, uiRes)) {
425            window.activeTabIndex = tabID; // instant visual feedback
426        }
427        currentX += tabWidth;
428    }
429
430    // TOP BUTTONS (ACTION GROUP BAR)
431    currentX = 20.0f; // reset X for action groups
432
433    const float buttonBaseHeight = 32.0f;
434    const float buttonGap = 4.0f;
435    const float subGroupGap = 18.0f;
436    const float groupGap = 28.0f;
437
438    uint32_t currentActionGroupIndex = 0xFFFFFFFF;
439    uint32_t currentSubGroupID = 0xFFFFFFFF;
440
441    float groupLabelY = ribbonY;
442    float subGroupLabelY = ribbonY + 18.0f;
443
444    for (size_t i = 0; i < TotalUIControls; ++i) {
445        const auto& ctrl = AllUIControls[i];
446
447        if (ctrl.actionGrpupIndex != currentActionGroupIndex) { // Action Group change
448            if (currentActionGroupIndex != 0xFFFFFFFF) currentX += groupGap;
449            currentActionGroupIndex = ctrl.actionGrpupIndex;
450            currentSubGroupID = 0xFFFFFFFF;
451
452            PushRect(ctx, currentX, groupLabelY, 6, 48, 0xFF555555, uiRes); // group separator
453            currentX += 12.0f;
454        }
455        
456        if (ctrl.actionSubGroupID != currentSubGroupID) { // Sub-Group change
457            if (currentSubGroupID != 0xFFFFFFFF) {currentX += subGroupGap;}
458            currentSubGroupID = ctrl.actionSubGroupID;
459
460            PushRect(ctx, currentX, subGroupLabelY, 110, 16, 0xFF2D2D30, uiRes); // sub-group label bar
461            currentX += 8.0f;
462        }
463
464        // Button geometry (vertical stacking support)
465        float btnWidth = (ctrl.defaultWidthPX > 0)
466            ? ctrl.defaultWidthPX * pixelsPerMM / 25.4f   // interpret as mm
467            : buttonWidthPx;
468        float btnHeight = buttonBaseHeight * ctrl.noOfVerticalSlots;
469        float btnY = ribbonY + 38.0f;
470
471        if (ctrl.noOfVerticalSlots > 1) {btnY += ctrl.verticalSlotNo * buttonBaseHeight;}
472        uint32_t baseColor = ctrl.isEnabled ? 0xFF2D2D30 : 0xFF1E1E1E;// Render
473
474        if (ctrl.type == 1 || ctrl.type == 2) {                     // Button or Dropdown trigger
475            bool clicked = PushInteractiveRect(ctx, currentX, btnY, btnWidth, btnHeight,
476                baseColor, (uint32_t)ctrl.action, input, uiRes, ctrl.isEnabled);
477
478            if (clicked && ctrl.isEnabled) {
479                PushUIAction((uint32_t)ctrl.action);
480                if (ctrl.zIndex == 1) { // Dropdown trigger
481                    window.activeDropdownAction = ctrl.action;
482                }
483            }
484
485            if (!ctrl.isEnabled) { // Gray-out overlay for disabled controls
486                PushRect(ctx, currentX, btnY, btnWidth, btnHeight, 0xAA333333, uiRes);
487            }
488        }
489        else if (ctrl.type == 3) {
490            // Future textbox
491            PushRect(ctx, currentX, btnY, btnWidth, btnHeight, 0xFF1E1E1E, uiRes);
492        }
493        else {
494            // Plain label
495            PushRect(ctx, currentX, btnY, btnWidth, btnHeight, 0xFF2D2D30, uiRes);
496        }
497
498        // Draw "x" below button
499        PushText(ctx, currentX, btnY + btnHeight + 14.0f, "x", 0xFFFFFFFF, uiRes);// below button
500        currentX += btnWidth + buttonGap;
501    }
502
503    currentX += 30.0f;// Final padding
504
505    // ACTIVE DROPDOWN (placeholder)
506    if (window.activeDropdownAction != UIAction::INVALID) {
507        float dropX = 400.0f;   // TODO: track real button X for proper positioning
508        float dropY = ribbonY + 80.0f;
509        PushRect(ctx, dropX, dropY, 160, 220, 0xFF1E1E1E, uiRes);
510        window.activeDropdownAction = UIAction::INVALID;   // immediate-mode auto-close
511    }
512
513    // DRAW ALL UI GEOMETRY
514    if (ctx.indexCount == 0) return;
515
516    D3D12_VERTEX_BUFFER_VIEW vbv{};
517    vbv.BufferLocation = uiRes.uiVertexBuffer->GetGPUVirtualAddress();
518    vbv.SizeInBytes = ctx.vertexCount * sizeof(UIVertex);
519    vbv.StrideInBytes = sizeof(UIVertex);
520
521    D3D12_INDEX_BUFFER_VIEW ibv{};
522    ibv.BufferLocation = uiRes.uiIndexBuffer->GetGPUVirtualAddress();
523    ibv.SizeInBytes = ctx.indexCount * sizeof(uint16_t);
524    ibv.Format = DXGI_FORMAT_R16_UINT;
525
526    cmd->IASetVertexBuffers(0, 1, &vbv);
527    cmd->IASetIndexBuffer(&ibv);
528    cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
529    cmd->DrawIndexedInstanced(ctx.indexCount, 1, 0, 0, 0);
530}

Miscellaneous philosophy:

Renderer must support these scripts:

Script Languages
Latin English, German, French, Spanish, Portuguese, Polish, Dutch, Swedish, Italian
Cyrillic Russian, Ukrainian
CJK Chinese, Japanese
Hangul Korean
Arabic Urdu
Indic Hindi, Bengali, Telugu, Tamil, etc
Thai Thai
Vietnamese Latin + diacritics

Recommended Font Families: NotoSans-Regular NotoSansCJK-Regular NotoSansDevanagari NotoSansTamil NotoSansTelugu NotoSansThai NotoSansArabic NotoSansHebrew