DirectX12 인덱스 버퍼 데이터 버그 디버깅 중..

2025. 3. 23. 17:32·공부/DirectX12

 정말 골치아픈 버그가 생겼고, 지금 얘 때문에 2주 정도 진전이 없다. 코드상에 문제가 전혀 없어보이기 때문인데다 PIX를 사용한 런타임 디버깅을 얼마 전에 알았기 때문이다.

 

 지금 엔진 테스팅으로 사용하고 있는 모델의 렌더링에 문제가 생기고있다. assimp를 사용해서 메시 데이터를 받아오는데 성공했고, 렌더링도 깔끔하게 잘 뽑혀서 전혀 문제가 없는 줄로만 알았다. 하지만 Skinned Mesh를 적용하기 위해서 씨름을 하던 중 뭔가 이상한 점을 발견했다.

미유 얼굴

 얼굴 오른편에 삐져나와있는 보기 싫은 글리치가 보이는가? 분명 뭔가 잘못 렌더링되고 있다는 뜻이다. 이상한게, 보통 어떤 한 모델에 렌더링 버그가 발생하면 통째로 뭉개지던가 해야되는데 일부만 저렇게 이상하게 렌더링 되는게 정말 이상했다. 당연히 CPU상에서 assimp를 통해 받아온 데이터에 문제가 있는건 아닌지 디버깅을 시작했다. 그리고 놀랍게도, 아무런 문제도 발견할 수 없었다.

 

 각 정점의 데이터는 물론이거니와 인덱스 버퍼에 들어갈 인덱스 데이터도 멀쩡하기만 했다. 모델을 읽어들이는 모듈은 문제가 없고... 그럼 엔진 코드의 문제거나 셰이더 코드의 문제일 것이다. 다행인지 모르겠지만 난 예제에서 사용되던 셰이더 코드를 아주 조금씩만 변형해서 사용했기 때문에 이쪽의 문제는 아니라고 생각된다. 아니 애초에 셰이더 코드가 잘못됐으면 다른 메시도 렌더링이 이상해야지..

 

 그럼 남은건 엔진 자체의 코드 문제다. 일주일간 디버깅을 했지만 문제가 뭔지, 뭐를 고쳐야하는지 전혀 갈피가 잡히지를 않았다. 그러던 중 PIX라는 그래픽 디버깅 툴을 알게되었다. 어플리케이션의 런타임 중 디버그를 도와주는 녀석으로, 그래픽 렌더링과 관련된 정보를 모두 확인할 수 있다. 그리고 여기서 문제점을 발견했다.

PIX 디버깅 화면

 문제가 발생한 서브메시의 인덱스 버퍼 내용물인데.. 그냥 얼핏봐도 이상하지 않은가?? 애초에 인덱스 버퍼의 데이터 갯수가 14010인데 처음부터 64114라는 터무니 없는 값이 들어가있다. CPU 상에서의 데이터 검증에서는 아무런 문제가 없었던 인덱스 버퍼의 데이터가 GPU로 넘어가는 과정에 무언가 문제가 생긴 것이 틀림없었다.

 

 여러 가지 가설을 세우고 코드를 이곳 저곳 고쳐보던 중, 해결은 아니지만 해당 렌더링 오류가 나타나고 사라지는 임계점(?)을 찾아냈다. 본인은 엔진에서 기본적으로 사용할 수 있는 도형으로 간단한 정육면체, 구, 평면을 미리 만들고 저장하고있다. 이 중에서 가장 데이터 크기가 큰 구의 메시 생성을 막자 렌더링이 정상적으로 되기 시작한 것이다.

 

 실마리는 잡았다. 메시와 관련된 데이터가 일정량을 넘기면 인덱스 버퍼를 생성하고 데이터를 넘겨주는 데에 문제가 발생한다. 하지만 왜..? 이유를 도통 모르겠다. 이 또한 짐작이지만, 까먹을 수 있기 때문에 글로 남겨본다.


1. 서브메시의 버퍼 생성 방식 문제

 당연하게도 지금 로드하고 사용하는 모델의 경우 통짜로 만들어진 모델이 아니다. 여러 서브메시들이 존재하고, 이 메시들이 모여서 하나의 모델을 이루는 것이다. 정점의 갯수가 매우 많고, 이 때문에 인덱스 정보를 하나의 버퍼에 모으면 오버플로우 문제가 발생한다. 최적화 문제를 해결하기 위해 정점의 데이터는 UINT16의 배열을 사용한다. 때문에 한 개의 인덱스 버퍼가 표현할 수 있는 최대 정점 갯수는 자연스래 UINT16의 최댓값인 65535를 따라가게 된다.

 

 때문에 각 메시의 정점 정보를 완전히 하나의 배열에 저장하는 것보다는 따로 저장해두고 그 다음 버퍼에 어떻게 나를지 고민하는 편이 합리적이라고 생각했다. 한 개의 메시에 단 하나의 버퍼를 생성해서 별도의 인덱싱을 통해 데이터를 전송하는 방법이 가장 이상적으로 보였지만 당장 빠르게 개발하기에는 각 서브메시마다 버퍼를 생성하는 것이 편리해보였다. 그래서 각 서브메시마다 버퍼를 생성하고 각각의 서브메시에 DrawCall을 했다.

 

 여기서 지나치게 많은 버퍼가 생성되었고 모종의 이유로 메모리 문제가 발생해서 최종적으로는 GPU로 넘어간 인덱스 버퍼에 문제가 발생했다는 가설이다. 사실 지금으로써는 가장 유력해 보이지만.. 그렇다고 이게 원인이다! 라고 확정지을만한 단서도 딱히 없기 때문에 섣불리 작업을 시작하기가 겁난다..

2. DirectX12의 데이터 관련 제한 문제

 DirectX 라이브러리에서는 여러 가지 데이터에 대해서 생성하는 양에 제한을 두고있다. 최적화 측면도 있고 데이터 처리에 문제가 발생할 수 있기 때문일 수도 있겠지만.. 이유야 어떻든 개발자 입장에선 그냥 따라야한다.

 

 필자가 알지 못하는, 라이브러리 자체에서 버퍼를 처리하는데 정해둔 마지노선이 있고 그걸 지키지 못해 인덱스 버퍼 데이터에 문제가 생겼다는게 두 번째 가설이다. 사실 이 부분에 대해서는 열심히 구글링을 해봤지만 그렇다할 단서를 찾지 못한 것은 마찬가지다..


 사실 이번에 PIX로 셰이더 파일을 디버깅하면서 새로운 사실도 알았다. 잘만 들어간다고 생각했던 Bone Weight 데이터와 Bone Index 데이터가 전혀 전송되고있지 않았다는 것이다. 알려준대로 따라한다고 따라했지만 내가 건드린 부분도 엄청나게 많기 때문에 참 이게 원인을 찾기가 점점 까다로워지는 것 같다. 아마 두 문제가 연결되어있는 것은 아닐까 의심도 든다. 일단은 이 렌더링 오류부터 해결하고 빠르게 Skinned Mesh 렌더링을 구현하도록하자...

 

+수정: Bone 관련 데이터가 넘어가지 않은건 그냥 내가 PSO를 안바꿔줘서 그랬던거다.. 이건 별개의 문제였던거로..

'공부 > DirectX12' 카테고리의 다른 글

툰 셰이딩에서 얼굴 명암 처리에 대해서  (0) 2025.04.04
앞으로의 개발 목표 정리  (0) 2025.03.29
DirectX 인덱스 버퍼 버그 해결  (0) 2025.03.23
DirectX12에서의 Descriptor Heap 크기에 대해  (0) 2025.03.09
DirectX에서의 회전 작업(LookAt 메소드 구현)에 대해서  (0) 2025.02.14
'공부/DirectX12' 카테고리의 다른 글
  • 앞으로의 개발 목표 정리
  • DirectX 인덱스 버퍼 버그 해결
  • DirectX12에서의 Descriptor Heap 크기에 대해
  • DirectX에서의 회전 작업(LookAt 메소드 구현)에 대해서
ayuriK152
ayuriK152
주로 게임 클라이언트 개발 공부를 해요 상용엔진이나 알고리즘 포스팅도 해요
  • ayuriK152
    아유릭공방
    ayuriK152
  • 전체
    오늘
    어제
    • 분류 전체보기 (24)
      • 공부 (19)
        • DirectX12 (11)
        • 유니티 (2)
        • 알고리즘(PS) (5)
      • 게임 (0)
        • 후기 (0)
      • 프로젝트 (5)
        • 리듬게임 프로젝트 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
ayuriK152
DirectX12 인덱스 버퍼 데이터 버그 디버깅 중..
상단으로

티스토리툴바