Mission Vishwakarma 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| Cyrillic      | Russian, Ukrainian, Bulgarian, etc    |
 81| Devanagari    | Hindi, Marathi, Nepali, Sanskrit etc  |
 82| Bengali       | Bengali, Assamese                     |
 83| Gurmukhi      | Punjabi                               |
 84| Gujarati      | Gujarati                              |
 85| Odia          | Odia                                  |
 86| Tamil         | Tamil                                 |
 87| Telugu        | Telugu                                |
 88| Kannada       | Kannada                               |
 89| Malayalam     | Malayalam                             |
 90| Meetei Mayek  | Manipuri (Meitei)                     |
 91| Ol Chiki      | Santali                               |
 92| Arabic script | Urdu, Arabic, Persian, Kashmiri       |
 93| Chinese Han   | Chinese + Japanese Kanji              |
 94| Japanese kana | Hiragana/Katakana                     |
 95| Hangul        | Korean                                |
 96| Thai          | Thai                                  |
 97
 98Professional CAD software language coverage (As per ChatGPT).
 99| Software   | Languages |
100| ---------- | --------- |
101| AutoCAD    | ~15       |
102| SolidWorks | ~13       |
103| Fusion360  | ~10       |
104| CATIA      | ~8        |
105All softwares listed below are copy right of respective software companies.
106
107HENCE OUR LANGUAGE LIST IS FROZEN ! ;)
108
109Estimated size overhead of bundling all the fonts:
110
111| Font                         | Typical Size |
112| ---------------------------- | ------------ |
113| Noto Sans (Latin + extended) | ~2 MB        |
114| Noto Sans Devanagari         | ~1.5 MB      |
115| Noto Sans Bengali            | ~1.3 MB      |
116| Noto Sans Gurmukhi           | ~0.9 MB      |
117| Noto Sans Gujarati           | ~1.0 MB      |
118| Noto Sans Oriya (Odia)       | ~1.1 MB      |
119| Noto Sans Tamil              | ~0.9 MB      |
120| Noto Sans Telugu             | ~1.2 MB      |
121| Noto Sans Kannada            | ~1.2 MB      |
122| Noto Sans Malayalam          | ~1.4 MB      |
123| Noto Sans Arabic             | ~1.2 MB      |
124| Noto Sans Thai               | ~0.7 MB      |
125
126Subtotal (non-CJK): ≈ 14–15 MB
127
128| Font                                   | Approx Size |
129| -------------------------------------- | ----------- |
130| Noto Sans CJK SC (Simplified Chinese)  | ~16–18 MB   |
131| Noto Sans CJK TC (Traditional Chinese) | ~16–18 MB   |
132| Noto Sans CJK JP (Japanese)            | ~16–18 MB   |
133| Noto Sans CJK KR (Korean)              | ~16–18 MB   |
134
135CJK 3 variants (SC + JP + KR): ≈ 48–54 MB
136
137Total: ≈ 65 MB , ~60% Compression expected in Installer. ≈ 40 MB. Acceptable.
138
139Runtime: Entire font files will not be loaded at runtime.
140They will be loaded on demand to minimize memory footprint.
141
142*/

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 <array>
13#include <unordered_map>
14#include <iostream>
15#include <atomic>
16
17#include "ConstantsApplication.h"
18#include "UserInterface.h" // It also includes "UserInterface-TextTranslations.h"
19
20// Do not #include "विश्वकर्मा.h" otherwise it will lead to circular dependency error. Declare this struct exist.
21struct SingleUIWindow; // Add this forward declaration:
22struct InternalSubTab;
23
24using Microsoft::WRL::ComPtr;
25
26struct DX12ResourcesUI { // GPU resources shared by all windows (read-only during recording).
27    // The dynamic vertex/index/ortho buffers live per window (DX12ResourcesPerWindow): all
28    // windows of a monitor are recorded into ONE command list and executed together, so a
29    // shared upload buffer would be overwritten by the last-recorded window.
30    std::array<ComPtr<ID3D12Resource>, UI_MAX_ATLAS_TEXTURES> uiAtlasTextures; // 1024×1024 or 2048×2048 RGBA (or R8 for alpha-only)
31
32    ComPtr<ID3D12PipelineState> uiPSO;
33    ComPtr<ID3D12RootSignature> uiRootSignature;
34    ComPtr<ID3D12DescriptorHeap> srvHeap;
35    ComPtr<ID3D12DescriptorHeap> samplerHeap;
36
37    uint32_t maxVertices = 65536;
38    uint32_t maxIndices = 65536 * 3;
39};
40
41// DirectX12 Immediate Mode UI System (Phase 4A). Tab Bar Rendering Only
42// External interfaces of User Interface sub module of the code. The platform-agnostic pieces
43// (UIDrawContext, Push* tessellation, PrecomputeTopRibbonLayout, BuildUIOverlay, atlas bitmap
44// builders) are declared in UserInterface.h and implemented in UserInterface.cpp.
45void InitUIResources(DX12ResourcesUI& uiRes, ID3D12Device* device);
46void CleanupUIResources(DX12ResourcesUI& uiRes);
47
48// Slots 0 and 1 are currently reserved for the mandatory English and Icon atlases.
49// Future script atlases can use slots [UI_FIRST_DYNAMIC_SCRIPT_ATLAS_SLOT, UI_MAX_ATLAS_TEXTURES).
50bool UploadUIAtlasTexture(DX12ResourcesUI& uiRes, ID3D12Device* device, uint32_t atlasSlot,
51    const AtlasBitmap& atlas);
52
53// (Re)builds monitor `monitorId`'s icon atlas at its DPI-floored icon cell size and (re)creates that
54// monitor's SRV heap (English@0 shared, icon@1 this monitor). Call from RestartRenderThreads while the
55// render threads are joined; the old atlas must already be drained + released (see RestartRenderThreads).
56void BuildMonitorIconAtlas(DX12ResourcesUI& uiRes, ID3D12Device* device, int monitorId);
57
58void RenderUIOverlay(SingleUIWindow& window, ID3D12GraphicsCommandList* cmdList,
59    DX12ResourcesUI& uiRes, UITopRibbonLayout& topRibbonLayout,
60    float monitorDPIX, float monitorDPIY, const UIInput& input,
61    uint64_t activeInternalSubTabMemoryId, int monitorId);
  1// Copyright (c) 2026-Present : Ram Shanker: All rights reserved.
  2
  3// DirectX12 half of the UI overlay module: atlas texture upload, PSO / root signature / sampler
  4// heap, per-window dynamic buffers and the actual draw call. The platform-agnostic half (atlas
  5// bitmap building, ribbon layout, tessellation, widget logic) lives in UserInterface.cpp.
  6
  7#include "UserInterface-DirectX12.h"
  8#include <algorithm>
  9#include <cstdio>
 10#include <d3dcompiler.h>
 11#include "ShaderUIVertex.h"
 12#include "ShaderUIPixel.h"
 13#include <MemoryManagerGPU-DirectX12.h>
 14#include "विश्वकर्मा.h"
 15#include "TextureSaver.h"
 16extern शंकर gpu;
 17extern void PrintHResult(int);
 18std::atomic<uint64_t> atlasFence = 0;
 19
 20bool SubmitTextureUpload(const TextureUploadDesc& desc,
 21    ComPtr<ID3D12Resource>* outTex,  std::atomic<uint64_t>* fenceOut) {
 22
 23    uint32_t index = gUploadQueue.writeIndex.fetch_add(1, std::memory_order_relaxed);
 24    UploadRequest& req = gUploadQueue.requests[index % MAX_UPLOAD_REQUESTS];
 25
 26    req.type = UploadType::Texture2D;
 27    req.texture = desc;
 28    req.outResource = outTex;
 29    req.completionFence = fenceOut;
 30
 31    return true;
 32}
 33
 34// Both UI/text root signatures declare their SRV range as all UI_MAX_ATLAS_TEXTURES descriptors with
 35// DESCRIPTOR_RANGE_FLAG_NONE, i.e. DESCRIPTORS_STATIC: every slot must hold a valid view before the
 36// table is bound, even the ones no shader samples. Point the not-yet-used slots at the English atlas;
 37// a real atlas uploaded into one of them later simply overwrites the alias.
 38static void FillSpareAtlasSlots(ID3D12DescriptorHeap* heap, ID3D12Resource* englishAtlasTexture,
 39    ID3D12Device* device, uint32_t firstSpareSlot) {
 40    if (!heap || !englishAtlasTexture || !device) return;
 41
 42    const UINT inc = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
 43    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
 44    srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
 45    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
 46    srvDesc.Texture2D.MipLevels = 1;
 47    srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
 48
 49    for (uint32_t slot = firstSpareSlot; slot < UI_MAX_ATLAS_TEXTURES; ++slot) {
 50        CD3DX12_CPU_DESCRIPTOR_HANDLE handle(heap->GetCPUDescriptorHandleForHeapStart(), slot, inc);
 51        device->CreateShaderResourceView(englishAtlasTexture, &srvDesc, handle);
 52    }
 53}
 54
 55bool UploadUIAtlasTexture(DX12ResourcesUI& uiRes, ID3D12Device* device, uint32_t atlasSlot,
 56    const AtlasBitmap& atlas) {
 57    if (!device || atlasSlot >= UI_MAX_ATLAS_TEXTURES || atlas.width <= 0 || atlas.height <= 0 ||
 58        atlas.pixels.empty() || (atlas.bytesPerPixel != 1 && atlas.bytesPerPixel != 4)) {
 59        return false;
 60    }
 61
 62    TextureUploadDesc desc = {};
 63    desc.width = atlas.width;
 64    desc.height = atlas.height;
 65    desc.format = atlas.bytesPerPixel == 4 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
 66    desc.pixels = atlas.pixels.data();
 67    desc.rowPitch = atlas.width * atlas.bytesPerPixel;
 68
 69    std::atomic<uint64_t> uploadFence = 0;
 70    SubmitTextureUpload(desc, &uiRes.uiAtlasTextures[atlasSlot], &uploadFence);
 71
 72    uint64_t atlasReadyFence = gpu.copyFenceValue.fetch_add(1, std::memory_order_relaxed);
 73    uploadFence.store(atlasReadyFence, std::memory_order_release);
 74    toCopyThreadCV.notify_one();
 75
 76    if (gpu.copyFence->GetCompletedValue() < atlasReadyFence) {
 77        ThrowIfFailed(gpu.copyFence->SetEventOnCompletion(atlasReadyFence, gpu.copyFenceEvent));
 78        WaitForSingleObject(gpu.copyFenceEvent, INFINITE);
 79    }
 80
 81    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
 82    srvDesc.Format = desc.format;
 83    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
 84    srvDesc.Texture2D.MipLevels = 1;
 85    srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
 86
 87    CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(uiRes.srvHeap->GetCPUDescriptorHandleForHeapStart(),
 88        atlasSlot, device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));
 89    device->CreateShaderResourceView(uiRes.uiAtlasTextures[atlasSlot].Get(), &srvDesc, srvHandle);
 90    return true;
 91}
 92
 93void BuildMonitorIconAtlas(DX12ResourcesUI& uiRes, ID3D12Device* device, int monitorId) {
 94    if (!device || monitorId < 0 || monitorId >= MV_MAX_MONITORS) return;
 95    OneMonitorController& screen = gpu.screens[monitorId];
 96
 97    // Icon cell size = this monitor's on-screen icon px. PrecomputeTopRibbonLayout (run by
 98    // RestartRenderThreads just before us) already floored the DPI, so iconSizePx is >= 20 on coarse
 99    // monitors. Fall back defensively if the layout has not been computed yet.
100    int cellSize = static_cast<int>(screen.topRibbonLayout.iconSizePx);
101    if (cellSize <= 0) cellSize = 20;
102
103    // Build the CPU atlas and fill this monitor's icon glyph lookup + metadata.
104    AtlasBitmap iconAtlas = BuildIconAtlas(cellSize, MonitorIconAtlasCPU(monitorId));
105
106    // Upload into this monitor's icon texture via the copy-queue path, then CPU-block until ready.
107    // Caller must have already drained + released any previous atlas for this monitor (RestartRenderThreads),
108    // so this write does not free a texture the GPU is still reading.
109    TextureUploadDesc desc = {};
110    desc.width = iconAtlas.width;
111    desc.height = iconAtlas.height;
112    desc.format = DXGI_FORMAT_R8G8B8A8_UNORM;
113    desc.pixels = iconAtlas.pixels.data();
114    desc.rowPitch = iconAtlas.width * iconAtlas.bytesPerPixel;
115
116    std::atomic<uint64_t> uploadFence = 0;
117    SubmitTextureUpload(desc, &screen.uiIconAtlasTexture, &uploadFence);
118    uint64_t atlasReadyFence = gpu.copyFenceValue.fetch_add(1, std::memory_order_relaxed);
119    uploadFence.store(atlasReadyFence, std::memory_order_release);
120    toCopyThreadCV.notify_one();
121    if (gpu.copyFence->GetCompletedValue() < atlasReadyFence) {
122        ThrowIfFailed(gpu.copyFence->SetEventOnCompletion(atlasReadyFence, gpu.copyFenceEvent));
123        WaitForSingleObject(gpu.copyFenceEvent, INFINITE);
124    }
125
126    // (Re)create this monitor's shader-visible SRV heap: English @ slot 0 (shared texture uploaded by
127    // InitUIResources) + icon @ slot 1 (this monitor's texture). Sized for future dynamic script atlases.
128    D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
129    heapDesc.NumDescriptors = UI_MAX_ATLAS_TEXTURES;
130    heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
131    heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
132    ThrowIfFailed(device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&screen.uiSrvHeap)));
133
134    const UINT inc = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
135    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
136    srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
137    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
138    srvDesc.Texture2D.MipLevels = 1;
139    srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
140
141    CD3DX12_CPU_DESCRIPTOR_HANDLE englishHandle(screen.uiSrvHeap->GetCPUDescriptorHandleForHeapStart(),
142        UI_ENGLISH_ATLAS_SLOT, inc);
143    device->CreateShaderResourceView(uiRes.uiAtlasTextures[UI_ENGLISH_ATLAS_SLOT].Get(), &srvDesc, englishHandle);
144
145    CD3DX12_CPU_DESCRIPTOR_HANDLE iconHandle(screen.uiSrvHeap->GetCPUDescriptorHandleForHeapStart(),
146        UI_ICON_ATLAS_SLOT, inc);
147    device->CreateShaderResourceView(screen.uiIconAtlasTexture.Get(), &srvDesc, iconHandle);
148
149    FillSpareAtlasSlots(screen.uiSrvHeap.Get(), uiRes.uiAtlasTextures[UI_ENGLISH_ATLAS_SLOT].Get(),
150        device, UI_FIRST_DYNAMIC_SCRIPT_ATLAS_SLOT);
151
152    char debugName[64];
153    std::snprintf(debugName, sizeof(debugName), "icon_atlas_debug_%d.bmp", monitorId);
154    SaveToBmp(debugName, iconAtlas.pixels.data(), iconAtlas.width, iconAtlas.height, iconAtlas.bytesPerPixel);
155
156    std::wcout << L"Icon atlas built for monitor " << monitorId << L" (cell " << cellSize << L" px)\n";
157}
158
159void InitUIResources( DX12ResourcesUI& uiRes, ID3D12Device* device) {
160    if (!InitFontSystem()) { // FONT system initialization (CPU-side)
161        std::cerr << "Font system initialization failed failed\n";
162        return;
163    }
164
165    // Root signature
166    CD3DX12_DESCRIPTOR_RANGE1 ranges[2]; // Descriptor ranges
167
168    // Range 0: SRV (t0)  → from srvHeap // 1: 1 Texture, 0: register t0 = atlas
169    ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, UI_MAX_ATLAS_TEXTURES, 0, 0,
170        D3D12_DESCRIPTOR_RANGE_FLAG_NONE);
171    // Range 1: SAMPLER (s0) → from samplerHeap // 1: 1 Sampler, 0: register s0 = sampler
172    ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_NONE);
173
174    CD3DX12_ROOT_PARAMETER1 rootParams[3];
175    rootParams[0].InitAsConstantBufferView(0, 0, D3D12_ROOT_DESCRIPTOR_FLAG_NONE,
176        D3D12_SHADER_VISIBILITY_VERTEX);// b0 - Ortho constant buffer (vertex shader)
177
178    // Root Parameter 1: Descriptor Table containing only the SRV
179    rootParams[1].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL);
180
181    // Root Parameter 2: Descriptor Table containing only the SAMPLER
182    rootParams[2].InitAsDescriptorTable(1, &ranges[1],
183        D3D12_SHADER_VISIBILITY_PIXEL);
184
185    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootDesc;
186    rootDesc.Init_1_1(_countof(rootParams), rootParams, 0, nullptr,
187        D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
188
189    ComPtr<ID3DBlob> signature;
190    ComPtr<ID3DBlob> errorBlob;
191
192    HRESULT hr = D3DX12SerializeVersionedRootSignature(&rootDesc,
193        D3D_ROOT_SIGNATURE_VERSION_1_1, &signature, &errorBlob);
194    if (FAILED(hr)) {
195        if (errorBlob)
196            std::cerr << "Root Signature Serialization Failed:\n"
197            << (char*)errorBlob->GetBufferPointer() << std::endl;
198        ThrowIfFailed(hr); // will print the real error
199    }
200
201    ThrowIfFailed(device->CreateRootSignature(0, signature->GetBufferPointer(),
202        signature->GetBufferSize(), IID_PPV_ARGS(&uiRes.uiRootSignature)));
203    uiRes.uiRootSignature->SetName(L"UI Overlay");
204    
205    // Create SRV descriptor heap (1 texture)
206    D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
207    heapDesc.NumDescriptors = UI_MAX_ATLAS_TEXTURES;
208    heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
209    heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
210    ThrowIfFailed(device->CreateDescriptorHeap( &heapDesc, IID_PPV_ARGS(&uiRes.srvHeap) ));
211
212    // Create SAMPLER descriptor heap (shader-visible)
213    D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = {};
214    samplerHeapDesc.NumDescriptors = 1;
215    samplerHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
216    samplerHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
217    ThrowIfFailed(device->CreateDescriptorHeap(&samplerHeapDesc,
218        IID_PPV_ARGS(&uiRes.samplerHeap)));
219
220    // Create the actual sampler.
221    D3D12_SAMPLER_DESC samplerDesc = {};
222    samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
223    samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
224    samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
225    samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
226    samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
227    samplerDesc.MinLOD = 0;
228    samplerDesc.MaxLOD = D3D12_FLOAT32_MAX;
229
230    device->CreateSampler(&samplerDesc,
231        uiRes.samplerHeap->GetCPUDescriptorHandleForHeapStart());
232
233    // Shaders are compiled to DXIL during the build and embedded into the executable.
234    // Input layout
235
236    D3D12_INPUT_ELEMENT_DESC layout[] = {
237        { "POSITION",0,DXGI_FORMAT_R32G32_FLOAT,0,0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 },
238        { "TEXCOORD",0,DXGI_FORMAT_R32G32_FLOAT,0,8, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 },
239        { "COLOR",0,DXGI_FORMAT_R32_UINT,0,16, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 },
240        { "TEXCOORD",1,DXGI_FORMAT_R32_UINT,0,20, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0 }
241    };
242
243    // PSO
244    D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
245    psoDesc.InputLayout = { layout,_countof(layout) };
246    psoDesc.pRootSignature = uiRes.uiRootSignature.Get();
247    psoDesc.VS = CD3DX12_SHADER_BYTECODE(g_uiVertexShader, sizeof(g_uiVertexShader));
248    psoDesc.PS = CD3DX12_SHADER_BYTECODE(g_uiPixelShader, sizeof(g_uiPixelShader));
249    psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
250    psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
251    psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
252    psoDesc.BlendState.RenderTarget[0].BlendEnable = TRUE;
253    psoDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
254    psoDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
255    psoDesc.DepthStencilState.DepthEnable = FALSE;
256    psoDesc.SampleMask = UINT_MAX;
257    psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
258    psoDesc.NumRenderTargets = 1;
259    psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
260    psoDesc.SampleDesc.Count = 1;
261
262    ThrowIfFailed( device->CreateGraphicsPipelineState( &psoDesc, IID_PPV_ARGS(&uiRes.uiPSO)));
263
264    // The dynamic vertex/index/ortho buffers are per window (DX12ResourcesPerWindow), created
265    // lazily by RenderUIOverlay (see EnsureWindowUIBuffers).
266    std::wcout << L"UI Resources Initialized (Phase 4A)\n";
267    
268    AtlasBitmap englishAtlas = BuildMSDFFontAtlas();
269    // The icon atlas is per monitor now (its cell size scales with DPI). It is built + uploaded and its
270    // SRV heap created by BuildMonitorIconAtlas from RestartRenderThreads. InitUIResources only handles
271    // the shared, DPI-independent English MSDF atlas below.
272
273    TextureUploadDesc desc = {};
274    desc.width = englishAtlas.width;
275    desc.height = englishAtlas.height;
276    desc.format = DXGI_FORMAT_R8G8B8A8_UNORM;
277    desc.pixels = englishAtlas.pixels.data();
278    desc.rowPitch = englishAtlas.width * englishAtlas.bytesPerPixel;
279
280    SubmitTextureUpload(desc, &uiRes.uiAtlasTextures[UI_ENGLISH_ATLAS_SLOT], &atlasFence);// Enqueue the upload through upload queue
281    // RESERVED FENCE VALUE FOR THIS UPLOAD (this is the key change)
282    // The copy thread MUST eventually signal exactly this value.
283    uint64_t atlasReadyFence = gpu.copyFenceValue.fetch_add(1, std::memory_order_relaxed);
284    // Tell everyone (including the render thread) what fence value to wait for
285    atlasFence.store(atlasReadyFence, std::memory_order_release);
286	toCopyThreadCV.notify_one(); // Wakeup CPU thread to process the newly uploaded texture.
287    // CPU-blocking wait until Copy Queue has processed this upload
288    if (gpu.copyFence->GetCompletedValue() < atlasReadyFence) {
289        ThrowIfFailed(gpu.copyFence->SetEventOnCompletion(atlasReadyFence, gpu.copyFenceEvent));
290        WaitForSingleObject(gpu.copyFenceEvent, INFINITE);   // CPU blocks here
291    }
292
293    // Now the texture is in DEFAULT heap → safe to create SRV
294    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
295    srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
296    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
297    srvDesc.Texture2D.MipLevels = 1;
298    srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
299    
300    device->CreateShaderResourceView(uiRes.uiAtlasTextures[UI_ENGLISH_ATLAS_SLOT].Get(), &srvDesc,
301        uiRes.srvHeap->GetCPUDescriptorHandleForHeapStart());
302
303    // This shared heap is only ever bound by the print path (PrinterController::Record2DDraws), which
304    // draws text and no icons — so the icon slot stays aliased here too. Icons come from the
305    // per-monitor heaps built by BuildMonitorIconAtlas, which own a real icon SRV at UI_ICON_ATLAS_SLOT.
306    FillSpareAtlasSlots(uiRes.srvHeap.Get(), uiRes.uiAtlasTextures[UI_ENGLISH_ATLAS_SLOT].Get(),
307        device, UI_ENGLISH_ATLAS_SLOT + 1);
308
309    std::wcout << L"Shared English MSDF atlas uploaded: slot " << UI_ENGLISH_ATLAS_SLOT
310        << L" (per-monitor icon atlases built by RestartRenderThreads)\n";
311}
312
313// Cleanup
314void CleanupUIResources(DX12ResourcesUI& uiRes) {
315    uiRes = {};
316}
317
318
319// Creates this window's dynamic UI buffers on first use. Per window by necessity: one monitor
320// command list records all its windows before executing, so a shared upload buffer would be
321// overwritten by the last-recorded window and every window would present that window's UI.
322static void EnsureWindowUIBuffers(DX12ResourcesPerWindow& winRes, ID3D12GraphicsCommandList* cmd,
323    const DX12ResourcesUI& uiRes) {
324    if (winRes.uiVertexBuffer) return;
325
326    ComPtr<ID3D12Device> device;
327    if (FAILED(cmd->GetDevice(IID_PPV_ARGS(&device)))) return;
328
329    auto uploadHeap = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
330
331    auto vbDesc = CD3DX12_RESOURCE_DESC::Buffer(uiRes.maxVertices * sizeof(UIVertex));
332    ThrowIfFailed(device->CreateCommittedResource(&uploadHeap, D3D12_HEAP_FLAG_NONE, &vbDesc,
333        D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&winRes.uiVertexBuffer)));
334
335    auto ibDesc = CD3DX12_RESOURCE_DESC::Buffer(uiRes.maxIndices * sizeof(uint16_t));
336    ThrowIfFailed(device->CreateCommittedResource(&uploadHeap, D3D12_HEAP_FLAG_NONE, &ibDesc,
337        D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&winRes.uiIndexBuffer)));
338
339    auto cbDesc = CD3DX12_RESOURCE_DESC::Buffer(256);
340    ThrowIfFailed(device->CreateCommittedResource(&uploadHeap, D3D12_HEAP_FLAG_NONE, &cbDesc,
341        D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&winRes.uiOrthoConstantBuffer)));
342
343    CD3DX12_RANGE readRange(0, 0);
344    winRes.uiVertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&winRes.pUIVertexDataBegin));
345    winRes.uiIndexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&winRes.pUIIndexDataBegin));
346    winRes.uiOrthoConstantBuffer->Map(0, &readRange, reinterpret_cast<void**>(&winRes.pUIOrthoDataBegin));
347}
348
349// This function renders the list of tabs, all top menu buttons (with dropdowns if required),
350// side favorite / frequent buttons bars, right side property window, bottom status bar.
351// This is also responsible for all relevant DirectX12 configurations required for rendering User Interface.
352void RenderUIOverlay(SingleUIWindow& window, ID3D12GraphicsCommandList* cmd, DX12ResourcesUI& uiRes,
353    UITopRibbonLayout& topRibbonLayout, float monitorDPIX, float monitorDPIY, const UIInput& input,
354    uint64_t activeInternalSubTabMemoryId, int monitorId) {
355
356    if (!cmd) return; //Defensive check.
357    if (monitorId < 0 || monitorId >= MV_MAX_MONITORS) return;
358
359    // This monitor's icon atlas + SRV heap (English@0 shared, icon@1 this monitor). Built by
360    // BuildMonitorIconAtlas in RestartRenderThreads; if not ready yet, skip UI this frame.
361    ID3D12DescriptorHeap* monitorSrvHeap = gpu.screens[monitorId].uiSrvHeap.Get();
362    if (!monitorSrvHeap) return;
363
364    EnsureWindowUIBuffers(window.dx, cmd, uiRes);
365    if (!window.dx.pUIVertexDataBegin || !window.dx.pUIIndexDataBegin ||
366        !window.dx.pUIOrthoDataBegin) {
367        return;
368    }
369
370
371    cmd->SetPipelineState(uiRes.uiPSO.Get());
372    cmd->SetGraphicsRootSignature(uiRes.uiRootSignature.Get());
373
374    // Bind descriptor heap
375    ID3D12DescriptorHeap* heaps[] = { monitorSrvHeap, uiRes.samplerHeap.Get() };
376    cmd->SetDescriptorHeaps(_countof(heaps), heaps);
377
378    // Bind the descriptor table (which contains t0 + s0)
379    // Root Parameter 1 = SRV table// must match rootParams[1]
380    cmd->SetGraphicsRootDescriptorTable(1, monitorSrvHeap->GetGPUDescriptorHandleForHeapStart());
381    // Root Parameter 2 = Sampler table
382    cmd->SetGraphicsRootDescriptorTable(2, uiRes.samplerHeap->GetGPUDescriptorHandleForHeapStart());
383    // Bind this window's ortho constant buffer (still root parameter 0)
384    cmd->SetGraphicsRootConstantBufferView(0, window.dx.uiOrthoConstantBuffer->GetGPUVirtualAddress());
385
386    float W = (float)window.dx.WindowWidth;
387    float H = (float)window.dx.WindowHeight;
388    float* ortho = (float*)window.dx.pUIOrthoDataBegin;
389
390    ortho[0] = 2 / W; ortho[1] = 0;   ortho[2] = 0; ortho[3] = -1;
391    ortho[4] = 0;   ortho[5] = -2 / H; ortho[6] = 0; ortho[7] = 1;
392    ortho[8] = 0;   ortho[9] = 0;   ortho[10] = 1; ortho[11] = 0;
393    ortho[12] = 0;  ortho[13] = 0;  ortho[14] = 0; ortho[15] = 1;
394
395    UIDrawContext ctx;
396    ctx.vertexPtr = reinterpret_cast<UIVertex*>(window.dx.pUIVertexDataBegin);
397    ctx.indexPtr = reinterpret_cast<uint16_t*>(window.dx.pUIIndexDataBegin);
398    ctx.vertexCount = 0;
399    ctx.indexCount = 0;
400
401    // Portable widget/hit-test half (UserInterface.cpp): fills ctx and emits UIActions.
402    BuildUIOverlay(window, ctx, uiRes, topRibbonLayout, monitorDPIX, monitorDPIY, input,
403        activeInternalSubTabMemoryId, monitorId);
404
405    // DRAW ALL UI GEOMETRY
406    if (ctx.indexCount == 0) return;
407
408    D3D12_VERTEX_BUFFER_VIEW vbv{};
409    vbv.BufferLocation = window.dx.uiVertexBuffer->GetGPUVirtualAddress();
410    vbv.SizeInBytes = ctx.vertexCount * sizeof(UIVertex);
411    vbv.StrideInBytes = sizeof(UIVertex);
412
413    D3D12_INDEX_BUFFER_VIEW ibv{};
414    ibv.BufferLocation = window.dx.uiIndexBuffer->GetGPUVirtualAddress();
415    ibv.SizeInBytes = ctx.indexCount * sizeof(uint16_t);
416    ibv.Format = DXGI_FORMAT_R16_UINT;
417
418    cmd->IASetVertexBuffers(0, 1, &vbv);
419    cmd->IASetIndexBuffer(&ibv);
420    cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
421    cmd->DrawIndexedInstanced(ctx.indexCount, 1, 0, 0, 0);
422}

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