# 機能設計書 267-imgui_impl_vulkan

## 概要

本ドキュメントは、Dear ImGuiのVulkanレンダラーバックエンド（imgui_impl_vulkan）の機能設計を定義する。

### 本機能の処理概要

Vulkanレンダラーバックエンドは、Dear ImGuiのUI描画コマンドをVulkan APIに変換し、画面にUIを描画する機能を提供する。SPIR-Vシェーダーを使用し、明示的なリソース管理とコマンドバッファベースのレンダリングを行う。

**業務上の目的・背景**：
Vulkanを使用するクロスプラットフォームアプリケーションにDear ImGuiを統合する必要がある場合に本バックエンドを使用する。VulkanはWindows、Linux、Android、macOS（MoltenVK経由）でサポートされ、最も低レベルな制御と最高のパフォーマンスを実現できる。

**機能の利用シーン**：
- Vulkanアプリケーションへの ImGuiデバッグUI追加
- クロスプラットフォームのハイパフォーマンスレンダリング
- VR/AR アプリケーションでのUI統合
- Dynamic Rendering（VK_KHR_dynamic_rendering / Vulkan 1.3）対応

**主要な処理内容**：
1. バックエンドの初期化（`ImGui_ImplVulkan_Init`）：InitInfo構造体による設定
2. デバイスオブジェクト作成（`ImGui_ImplVulkan_CreateDeviceObjects`）：パイプライン、ディスクリプタセットレイアウト作成
3. フレーム開始処理（`ImGui_ImplVulkan_NewFrame`）：状態確認
4. 描画データのレンダリング（`ImGui_ImplVulkan_RenderDrawData`）：コマンドバッファへの記録
5. テクスチャ更新（`ImGui_ImplVulkan_UpdateTexture`）：ステージングバッファ経由の転送
6. テクスチャ登録（`ImGui_ImplVulkan_AddTexture`）：ユーザーテクスチャ用ディスクリプタセット作成
7. バックエンドの終了処理（`ImGui_ImplVulkan_Shutdown`）：リソース解放

**関連システム・外部連携**：
- プラットフォームバックエンド（GLFW、SDL、Win32等）と組み合わせて使用
- Vulkanランタイム
- Volk対応（オプショナル）

**権限による制御**：
特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面 | 主画面 | すべてのDear ImGuiウィジェットの描画出力先 |

## 機能種別

レンダリングバックエンド / グラフィックスAPI抽象化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|-----------------|
| info | ImGui_ImplVulkan_InitInfo* | Yes | 初期化設定構造体 | Device/Queue必須 |
| draw_data | ImDrawData* | Yes | 描画コマンドリスト | DisplaySize > 0 |
| command_buffer | VkCommandBuffer | Yes | コマンドバッファ | VK_NULL_HANDLE以外 |
| pipeline | VkPipeline | No | 使用するパイプライン | 省略時は内部Pipeline使用 |

### ImGui_ImplVulkan_InitInfo構造体

| フィールド名 | 型 | 必須 | 説明 |
|-------------|-----|-----|------|
| ApiVersion | uint32_t | Yes | Vulkan APIバージョン |
| Instance | VkInstance | Yes | Vulkanインスタンス |
| PhysicalDevice | VkPhysicalDevice | Yes | 物理デバイス |
| Device | VkDevice | Yes | 論理デバイス |
| QueueFamily | uint32_t | Yes | キューファミリインデックス |
| Queue | VkQueue | Yes | グラフィックスキュー |
| DescriptorPool | VkDescriptorPool | No | ディスクリプタプール（DescriptorPoolSize=0時必須） |
| DescriptorPoolSize | uint32_t | No | 自動作成時のプールサイズ |
| MinImageCount | uint32_t | Yes | 最小イメージ数（>= 2） |
| ImageCount | uint32_t | Yes | イメージ数（>= MinImageCount） |
| PipelineCache | VkPipelineCache | No | パイプラインキャッシュ |
| PipelineInfoMain | ImGui_ImplVulkan_PipelineInfo | Yes | パイプライン設定 |
| UseDynamicRendering | bool | No | Dynamic Rendering使用フラグ |
| Allocator | VkAllocationCallbacks* | No | カスタムアロケータ |
| CheckVkResultFn | function | No | エラーチェックコールバック |
| MinAllocationSize | VkDeviceSize | No | 最小割り当てサイズ |
| CustomShaderVertCreateInfo | VkShaderModuleCreateInfo | No | カスタム頂点シェーダー |
| CustomShaderFragCreateInfo | VkShaderModuleCreateInfo | No | カスタムフラグメントシェーダー |

### 入力データソース

- ImGui_ImplVulkan_InitInfo構造体
- ImDrawData構造体
- ImTextureData構造体

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 初期化結果 | bool | Init関数の成功/失敗 |
| テクスチャID | VkDescriptorSet | ディスクリプタセット |
| コマンドバッファ出力 | Vulkanコマンド | コマンドバッファへの描画コマンド記録 |

### 出力先

- Vulkanコマンドバッファ
- io.BackendRendererUserData
- platform_io.Renderer_RenderState（コールバック用）

## 処理フロー

### 処理シーケンス

```
1. ImGui_ImplVulkan_Init(info)
   ├─ VulkanInitInfo構造体のコピー
   ├─ NonCoherentAtomSizeの取得
   ├─ ディスクリプタプール作成（オプショナル）
   └─ CreateDeviceObjects呼び出し

2. ImGui_ImplVulkan_CreateDeviceObjects()
   ├─ CreateSampler（Linear）
   ├─ CreateDescriptorSetLayout
   ├─ CreatePipelineLayout（PushConstants使用）
   ├─ CreateShaderModule（SPIR-V）
   ├─ CreateGraphicsPipelines
   └─ CreateCommandPool / CreateCommandBuffer

3. [毎フレーム] ImGui_ImplVulkan_NewFrame()
   └─ 特になし（状態確認のみ）

4. [毎フレーム] ImGui_ImplVulkan_RenderDrawData(draw_data, command_buffer)
   ├─ テクスチャ更新
   ├─ VB/IB作成・拡張
   ├─ vkMapMemory / vkUnmapMemory（データアップロード）
   ├─ vkFlushMappedMemoryRanges
   ├─ SetupRenderState
   │      ├─ vkCmdBindPipeline
   │      ├─ vkCmdBindVertexBuffers / vkCmdBindIndexBuffer
   │      ├─ vkCmdSetViewport
   │      └─ vkCmdPushConstants
   ├─ RenderState設定（コールバック用）
   └─ 描画コマンド実行
          ├─ vkCmdSetScissor
          ├─ vkCmdBindDescriptorSets
          └─ vkCmdDrawIndexed

5. ImGui_ImplVulkan_UpdateTexture(tex)
   ├─ vkCreateImage（VK_IMAGE_TILING_OPTIMAL）
   ├─ vkAllocateMemory（DEVICE_LOCAL）
   ├─ vkCreateImageView
   ├─ ImGui_ImplVulkan_AddTexture（ディスクリプタセット作成）
   ├─ vkCreateBuffer（ステージングバッファ）
   ├─ vkMapMemory / vkUnmapMemory
   ├─ vkCmdPipelineBarrier（UNDEFINED → TRANSFER_DST）
   ├─ vkCmdCopyBufferToImage
   ├─ vkCmdPipelineBarrier（TRANSFER_DST → SHADER_READ_ONLY）
   ├─ vkQueueSubmit
   └─ vkQueueWaitIdle

6. ImGui_ImplVulkan_Shutdown()
   └─ DestroyDeviceObjects
```

### フローチャート

```mermaid
flowchart TD
    A[Init] --> B[CreateDeviceObjects]
    B --> C[NewFrame]
    C --> D[RenderDrawData]
    D --> E[Update Textures]
    E --> F[Create/Resize VB/IB]
    F --> G[Map/Flush/Unmap Memory]
    G --> H[SetupRenderState]
    H --> I[vkCmdBindPipeline]
    I --> J[vkCmdPushConstants]
    J --> K[For each DrawList/DrawCmd]
    K --> L[vkCmdSetScissor]
    L --> M[vkCmdBindDescriptorSets]
    M --> N[vkCmdDrawIndexed]
    N --> O[Shutdown]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | シェーダー形式 | SPIR-V（GLSL 450 core相当） | シェーダーモジュール作成時 |
| BR-002 | テクスチャ形式 | VK_FORMAT_R8G8B8A8_UNORM | テクスチャ作成時 |
| BR-003 | 大規模メッシュ対応 | 64K頂点以上サポート | vkCmdDrawIndexedのVtxOffset使用 |
| BR-004 | イメージ数管理 | ImageCount分のフレームバッファ | マルチバッファリング |
| BR-005 | ディスクリプタセット | VkDescriptorSetをテクスチャIDとして使用 | テクスチャバインド時 |
| BR-006 | PushConstants | scale/translate用に16バイト | 頂点シェーダー |

### 計算ロジック

**スケール・トランスレート計算**（行511-518）:
```cpp
float scale[2];
scale[0] = 2.0f / draw_data->DisplaySize.x;
scale[1] = 2.0f / draw_data->DisplaySize.y;
float translate[2];
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
```

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IM_ASSERT | 初期化エラー | 二重初期化 | 初期化状態確認 |
| VkResult | Vulkanエラー | 各API呼び出し失敗 | CheckVkResultFnで通知 |
| 0xFFFFFFFF | メモリタイプ検索失敗 | 適切なメモリタイプなし | return |

### リトライ仕様

リトライなし

## トランザクション仕様

該当なし

## パフォーマンス要件

- VK_MEMORY_PROPERTY_HOST_VISIBLE_BITメモリでVB/IBアップロード
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BITメモリでテクスチャ格納
- vkFlushMappedMemoryRangesによる明示的メモリ同期
- NonCoherentAtomSizeでアライメント調整
- BufferMemoryAlignmentの動的更新

## セキュリティ考慮事項

- デバイスポインタの検証
- CheckVkResultFnコールバックによるエラー検出

## 備考

- IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPESでカスタムローダー対応
- IMGUI_IMPL_VULKAN_USE_VOLKでVolk対応
- VK_KHR_dynamic_rendering / Vulkan 1.3のDynamic Rendering対応
- ImGui_ImplVulkan_AddTexture()でユーザーテクスチャ登録
- ImGui_ImplVulkanH_XXX ヘルパー関数群はサンプル用（エンジン統合には非推奨）

---

## コードリーディングガイド

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_impl_vulkan.h | `backends/imgui_impl_vulkan.h` | ImGui_ImplVulkan_InitInfo構造体（行102-137）を確認 |
| 1-2 | imgui_impl_vulkan.h | `backends/imgui_impl_vulkan.h` | ImGui_ImplVulkan_PipelineInfo構造体（行84-92）を確認 |
| 1-3 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | ImGui_ImplVulkan_Data構造体（行265-293）を確認 |
| 1-4 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | ImGui_ImplVulkan_Texture構造体（行254-262）を確認 |

**読解のコツ**: Vulkanは明示的なリソース管理が必要なため、メモリタイプ、アライメント、ディスクリプタセットなど多数のメンバーを持つ。

#### Step 2: SPIR-Vシェーダーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | 頂点シェーダーGLSLコメント（行299-316）を確認 |
| 2-2 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | __glsl_shader_vert_spv配列（行318-361）を確認 |
| 2-3 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | フラグメントシェーダーGLSLコメント（行363-373）を確認 |
| 2-4 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | __glsl_shader_frag_spv配列（行375-402）を確認 |

**主要処理フロー**:
- **頂点シェーダー**: push_constant経由でscale/translateを受け取り、gl_Positionを計算
- **フラグメントシェーダー**: combined_image_samplerでテクスチャサンプリング

#### Step 3: レンダリング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | RenderDrawData関数（行522-674）を確認 |
| 3-2 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | SetupRenderState関数（行478-520）を確認 |

**主要処理フロー**:
- **行556-564**: VB/IB作成・拡張（CreateOrResizeBuffer）
- **行566-591**: vkMapMemory / vkFlushMappedMemoryRanges / vkUnmapMemory
- **行517-518**: vkCmdPushConstants（scale/translate）
- **行657**: vkCmdDrawIndexed

#### Step 4: テクスチャ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | UpdateTexture関数（行696-）を確認 |

**主要処理フロー**:
- **行714-739**: vkCreateImage / vkAllocateMemory / vkBindImageMemory
- **行744-753**: vkCreateImageView
- **行757**: ImGui_ImplVulkan_AddTexture（ディスクリプタセット作成）
- **行783-800**: ステージングバッファ作成

### プログラム呼び出し階層図

```
アプリケーション
    │
    ├─ ImGui_ImplVulkan_Init(info)
    │      ├─ VulkanInitInfo コピー
    │      ├─ vkGetPhysicalDeviceProperties()
    │      │      └─ NonCoherentAtomSize 取得
    │      ├─ vkCreateDescriptorPool() [オプショナル]
    │      └─ ImGui_ImplVulkan_CreateDeviceObjects()
    │             ├─ vkCreateSampler()
    │             ├─ vkCreateDescriptorSetLayout()
    │             ├─ vkCreatePipelineLayout()
    │             ├─ vkCreateShaderModule() [vert/frag]
    │             ├─ vkCreateGraphicsPipelines()
    │             └─ vkCreateCommandPool() / vkAllocateCommandBuffers()
    │
    ├─ [フレームループ]
    │      │
    │      ├─ ImGui_ImplVulkan_NewFrame()
    │      │
    │      └─ ImGui_ImplVulkan_RenderDrawData()
    │             ├─ ImGui_ImplVulkan_UpdateTexture()
    │             │      ├─ vkCreateImage()
    │             │      ├─ vkAllocateMemory()
    │             │      ├─ vkCreateImageView()
    │             │      ├─ ImGui_ImplVulkan_AddTexture()
    │             │      │      ├─ vkAllocateDescriptorSets()
    │             │      │      └─ vkUpdateDescriptorSets()
    │             │      ├─ vkCreateBuffer() [ステージング]
    │             │      ├─ vkMapMemory() / vkUnmapMemory()
    │             │      ├─ vkCmdPipelineBarrier()
    │             │      ├─ vkCmdCopyBufferToImage()
    │             │      ├─ vkQueueSubmit()
    │             │      └─ vkQueueWaitIdle()
    │             │
    │             ├─ CreateOrResizeBuffer() [VB/IB]
    │             ├─ vkMapMemory() / vkFlushMappedMemoryRanges() / vkUnmapMemory()
    │             ├─ ImGui_ImplVulkan_SetupRenderState()
    │             │      ├─ vkCmdBindPipeline()
    │             │      ├─ vkCmdBindVertexBuffers()
    │             │      ├─ vkCmdBindIndexBuffer()
    │             │      ├─ vkCmdSetViewport()
    │             │      └─ vkCmdPushConstants()
    │             │
    │             ├─ vkCmdSetScissor()
    │             ├─ vkCmdBindDescriptorSets()
    │             └─ vkCmdDrawIndexed()
    │
    └─ ImGui_ImplVulkan_Shutdown()
           └─ ImGui_ImplVulkan_DestroyDeviceObjects()
```

### データフロー図

```
[入力]                         [処理]                              [出力]

ImGui_ImplVulkan_InitInfo ──▶ Init() ───────────────────────▶ バックエンドデータ
  ├─ Instance                  ├─ VulkanInitInfo コピー           └─ Pipeline
  ├─ PhysicalDevice            ├─ NonCoherentAtomSize 取得         └─ DescriptorSetLayout
  ├─ Device                    └─ CreateDeviceObjects()
  ├─ Queue
  ├─ DescriptorPool
  └─ PipelineInfoMain

ImDrawData ─────────────▶ RenderDrawData() ───────────▶ VkCommandBuffer
  ├─ DisplaySize               ├─ CreateOrResizeBuffer()           └─ 描画コマンド記録
  ├─ FramebufferScale          ├─ vkMapMemory()
  ├─ CmdLists[]                ├─ SetupRenderState()
  │   ├─ VtxBuffer             │      └─ vkCmdPushConstants()
  │   └─ IdxBuffer             └─ vkCmdDrawIndexed()
  │
  └─ Textures[] ──────────▶ UpdateTexture() ──────────▶ VkDescriptorSet
       └─ ImTextureData       ├─ vkCreateImage()
                              ├─ vkCreateImageView()
                              ├─ ImGui_ImplVulkan_AddTexture()
                              │      └─ vkUpdateDescriptorSets()
                              ├─ vkCmdCopyBufferToImage()
                              └─ vkQueueSubmit() / vkQueueWaitIdle()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui_impl_vulkan.h | `backends/imgui_impl_vulkan.h` | ヘッダー | 公開API宣言、InitInfo/PipelineInfo/RenderState構造体、ヘルパー関数（275行） |
| imgui_impl_vulkan.cpp | `backends/imgui_impl_vulkan.cpp` | ソース | バックエンド実装本体、SPIR-Vシェーダー埋め込み |
| vulkan/vulkan.h | システム | ヘッダー | Vulkan API宣言 |
| volk.h | オプショナル | ヘッダー | Vulkan関数ローダー（Volk） |
