이번에 한 작업은 ImGui 라이브러리를 수정했다.
Texture와 TextureView를 분리하면서 TextureView가 ImGui::Image에 핸들을 제공하는 역할을 담당하게 되었는데
Vulkan만 다른 API들과 다른 방법으로 사용하도록 imgui에서 설명하고 있었다.
ImGui::Image는 64비트 정수 타입의 ImTextureID라는 값을 요구하는데
이 값은 API마다 다른 타입을 캐스팅 해서 전달한다.
DX11 = ID3D11ShaderResourceView*
DX12 = D3D12_CPU_DESCRIPTOR_HANDLE
OpenGL = GLuint
이다.
이 값을 ImTextureID로 캐스팅 해서 전달하면 내가 생성한 텍스쳐를 imgui에서 보이도록 할 수 있다.
그러나 ImGui 개발자도 Vulkan의 기괴한 구조를 다른 API와 통일하는 데에는 실패한 듯 했다.
역시나 또 문제는 DescriptorSet이었다.
Vulkan에서 ImGui::Image함수를 사용하기 위해서는
VkDescriptorSet 을 요구한다.
https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
Image Loading and Displaying Examples
Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies - ocornut/imgui
github.com
여기서 vulkan 파트를 보자.

다른 API들은 사용자가 직접 srv를 만들거나(dx11,12), 직접 만든 텍스쳐ID(opengl)를 사용하는데
Vulkan만 imgui에서 제공하는 함수를 사용해서 별개의 VkDescriptorSet을 멤버로 추가하고 imgui가 만들어준걸 받아서 써야한다.

내 프로그램에서 만든게 아니기 때문에 이것도 imgui에서 제공하는 함수를 써서 해제해줘야 한다.
이것도 사용자 편의성을 최대한 고려해서 만든 것이겠지만 나는 이 방식이 불편하다고 생각했다.
물론 imgui vulkan 백엔드 코드에서 어떤식으로 vkDescriptorSet을 만드는지 보고 ImGui에서 제공하는 함수를 사용하지 않고 직접 생성할 수도 있지만 이 경우 TextureView에 ImGui에서 사용하기 위한 VkDescriptorSet을 별도의 멤버로 추가해야 했고
나는 이 문제를 해결하고 싶어서 이미 VkPushDescriptorSet이라는 기능을 도입했고 VkDescriptorSet은 쳐다보기 싫었다.
DX11, DX12, OpenGL이 ImTextureID로 캐스팅해서 사용하는 타입들과 비교해서 보자면
Vulkan에도 VkImageView라는 타입이 있다.
나는 ImTextureID로 VkDescriptorSet대신 VkImageView를 전달할 수 있다면 다른 API들과 비슷한
사용법을 가지게 되어 매우 편리할 것이라는 생각이 들었고
VkPushDescriptorSet기능(Vulkan1.4 버전 이상)을 이용하면 위에서 설명한 기능이 동작하도록
imgui를 수정하고 이걸로 오픈소스에 PR도 해보자. 라는 계획을 세우게 되었다.
기존의 기능을 유지하면서 새로운 기능을 추가하는 방향으로 코드를 작성했다.

Vulkan에서 dynamic rendering을 도입한 방식을 그대로 따라서 매크로를 정의해주었다.

마찬가지로 ImGui_ImplVulkan_InitInfo 에 플래그를 추가해줬다.
1.4에서 도입된 기능이라는 것은 그 이전 버전에서는 제대로 동작하지 않는 코드라는 것이고,
imgui는 이런 문제를 해결하기 위해 새로운 기능을 선택적으로 제공하는 것 같아서 나도 방식에 따르기로 했다.

이후로도 계속 똑같이 그냥 Dynamic Rendering을 구현한 방식을 모방하면 됐기 때문에 편하게 코드를 수정할 수 있었다.

ImGui_ImplVulkan_RenderDrawData 함수가 변경의 핵심인데
원래는 GetTexID()를 VkDescriptorSet타입으로 받고 vkCmdBindDescriptorSets를 사용했다면
VkCmdPushDescriptorSet 기능이 지원되고 사용자가 플래그를 활성화 한경우
GetTexID()를 VkImageView타입으로 받고 vkCmdPushDescriptorSet 함수를 통해서 텍스쳐를 바인딩 하는 것이다.
GetTexID가 가져오는 값은 ImGui::Image함수를 보면

내부적으로 ImTextureRef에 값을 받게 되고

우리가 ImGui::Image에 ImTextureID로 캐스팅해서 전달한 포인터가 저렇게 ImTextureRef(ImTextureID)로 들어가서 DrawList에 추가되고
백엔드에서 GetTexID를 통해 가져온 포인터를 다시 원래 타입으로 캐스팅 해서 쓰는 구조로 대충 이해하면 될 것같다.

그리고 DescriptorSetLayout 생성시 플래그가 필요하기 때문에 추가해줬다.

이것도 Dynamic Rendering 기능에서 구현한 로드함수를 따라서 구현해줬다.


기존에 vkDescriptorSet을 받기 위해 사용해야 했던 함수들은 usePushDescriptorSet 플래그가 활성화된 경우 사용이 불가능하도록 변경해주었다.
그리고 AI의 도움을 받아서 뭐 매크로를 추가해야할 부분을 더 추가해줬다.

TextureView에서 ImGui때문에 어쩔수없이 멤버로 넣었던 VkDescriptorSet을 제거하고 VkImageView를 리턴하도록 수정했다.
이제 imgui의 docking 브랜치 기준으로
다른 API와 동일한 방식으로 imageView를 전달해서 이미지를 띄우는 것을 확인할 수 있었다.
이전 글과 같은 실행화면이라 따로 실행화면은 첨부하지 않았다.

imgui에 pr도 해봤는데 별다른 답변은 아직 받지 못했지만
개인적으로 변경사항이 마음에 들기 때문에 유지할 것 같다.
'개인 공부 및 프로젝트 > Daydream Engine' 카테고리의 다른 글
| 자체 게임엔진 DevLog - 파일 시스템, 렌더러 수정 (0) | 2026.06.01 |
|---|---|
| 자체 게임엔진 DevLog - Texture Class 리팩토링 (0) | 2026.05.20 |
| 자체 게임엔진 DevLog - 디버깅 자체가 뻗어버리는 문제 (0) | 2026.05.05 |
| 자체 게임엔진 DevLog - RenderGraph 작성 (0) | 2026.04.29 |
| 자체 게임엔진 DevLog - 버퍼 클래스 구조 수정 (0) | 2026.04.29 |