Computer Graphics/Vulkan

Vulkan Game Engine - 21. 엔진 문제와 해결 방안 고민 (최적화)

surkim 2025. 3. 12. 15:40

드디어 최적화까지 왔다!

이 부분만 해결하면 사실상 과제에서 요구하는 기능들은 전부 구현한 것이고

추가하고싶은 기능은 너무 많은데 내 욕심이고 기다리고 있는 동료들에게 예의가 아니라

다른 프로젝트에서 하든 평가를 받고 추가하든 해야겠다.

 

 

ui만 draw호출을 하고 viewport를 텍스쳐하나로 퉁쳤는데도 240이 안된다.

 

우선 문제점은 씬에 오브젝트를 1000개 만들때 있다.

오브젝트를 1000개 배치하고 프레임이 생각보다 너무 떨어져서 확인했을때

우리엔진 파이프라인 구성상 큰 오버헤드가 발생할 구석이 없어서 

cpu 병목인가 하고 살펴봤는데 cpu에서는 더더욱 병목이 일어날 일이 없었고

gpu병목이면 draw호출을 없애보자하고

씬을 그리지 않고 텍스쳐만 그리게 draw호출을 바꿔봤는데도 프레임드랍이 일어나서

원인을 못찾아서 아.. 큰일났다 이건 정말 큰일이다.. 했는데

다행히 동료의 컴퓨터로 debug 모드를 돌렸을때 

validation layer: Validation Error: [ VUID-vkAllocateMemory-maxMemoryAllocationCount-04101 ] 
| MessageID = 0x4e9256cc | vkAllocateMemory():  
vkAllocateMemory: Number of currently valid memory objects is not less than maxMemoryAllocationCount (4096).


이런 validation layer에러가 나서 원인을 찾을 수 있었다.

왜 내 컴퓨터로는 저 에러가 안나는지 모르겠지만

그건 나중에 알아보도록하고 우선 원인을 찾아서 다행이다!

 

정확한 원인을 말하자면 

오브젝트를 그리기 위해서 RenderingComponent가 생성되는데

이 RenderingComponent가 생성될 때 그림자를 그릴 descriptorset 16개와 ((shadow map 4 + shadow cubemap 4) * 작업할 프레임 수 2), 지연렌더링에 필요한 descriptorset 2개 * submesh 개수 만큼 생성된다. submesh 개수만큼 descriptorset을 생성했던것은 submesh별 material을 다르게 넣어줄 수 있기 때문에 이렇게 생성했었다.

 

그럼 RenderingComponent가 생성되면 최소 18개의 descriptorset이 생성되고

개수가 많을 수록 기하급수적으로 늘어나게 된다. (1000개 오브젝트면 최소 18000개의 descriptorset)

이건 내가 알고도 이렇게 했었다.. ㅎ

vulkan 인스턴스는 메모리가 닿는데까지 생성하는 줄 알았지

4096개로 제한되어 있는줄 몰랐기 때문이다..

뭐 그래도 이제 알았으니 해결하면 된다!

 

해결 방안을 곰곰히 생각해봤는데

일단 예전부터 Scene소속인 RenderingComponent가 vulkan자원인 descriptorset을 가지고 있는게 꼴보기 싫었다.

이걸 Renderer클래스로 이전하려고 한다.

RenderingComponent는 model을 참조하고 있는데 이 model클래스가 mesh들을 가지고 있고

같은 모델이면 같은 주소값을 참조하고 있으니깐

RenderingComponent를 생성하면서 model을 참조할 때

model에서 본인을 참조하고 있는 RenderingCoponent개수를 알면

굳이 컴포넌트 생성될 때마다 만들 필요없이 한 descriptorset으로 한방에 draw호출을 하는 방식으로 할 수 있지 않을까?라고 전략을 짰다.

 

아직 안해봐서 닥칠 문제가 뭔지 모른다.

뭔가 냄새가 나는 부분은 같은 모델 다른 material일 때는 어떻게 해야하지 정도?

해보고오겠다!