인프런 커뮤니티 질문&답변

dltmddnr05님의 프로필 이미지

작성한 질문수

D3D12 프로그래밍 - 기초편

질문있습니다.

24.07.10 09:54 작성

·

191

·

수정됨

0

 

안녕하세요 공부하다가 몇가지 궁금한게 생겨 여쭤봅니다.

 

질문1) 

D3D12_DESCRIPTOR_RANGE ranges[2] =

{

{ D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 5, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND }, // b0 ~ b4

{ D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 5, 0, 0, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND } // t0 ~ t4

};

 

CD3DX12_ROOT_PARAMETER rootParameters[1] = {};

rootParameters[0].InitAsDescriptorTable(_countof(ranges), ranges, D3D12_SHADER_VISIBILITY_ALL);

 

와 같이 루트시그니처에서 테이블의 사용범위를 넓게잡아두고

사용할때만 Shader 에서 buffer를 정의 ( ex :cbuffer WVP: register(b0 )해서

사용해주고있는데 테이블힙의 메모리 낭비를 제외하면 성능에 큰 악영향이 있을까요?

런타임에 터지거나 하는 오류는 현재 없는데 궁금해서 여쭤봅니다.

 

질문2)제목 없음.png제가 이해한게 맞는건지 모르겠습니다.

 

현재 영천님 의 코드처럼 pool 방식으로 디스크럽터를 넓게만들어두고 할당받는 방식으로 코드를 만들어보고있는데

질문1의 방식처럼 rootSignature 를 만들었다고 하였을때 ,

SetGraphicsRootDescriptorTable 함수인자에 핸들값을 넣을때

그림에 빨간 화살표에 있는 선두에 있는 handle 값만 넣어주면

RootSignature 에서는 b0~b5 ,t0~t5 의 총10개를 사용한다고 서명했기떄문에 ,

DX에서 읽을때 10개단위로 읽어주기 때문에 10개가 모두 테이블에 바인딩되는 구조인가요?

다음 오브젝트를 그릴때는 , 오프셋 10칸을 건너뛴 다음 b0 부터 할당받아서 테이블에 바인딩해주고

 

 

답변 1

0

인프런 AI 인턴님의 프로필 이미지

2024. 07. 11. 09:56

안녕하세요, 인프런 AI 인턴입니다.

dltmddnr05님의 질문에 대한 답변입니다.

질문1에 대한 답변:
루트 시그니처에서 디스크립터 테이블의 사용 범위를 넓게 잡아두고 필요할 때만 셰이더에서 버퍼를 정의하여 사용하는 방식은, 테이블 힙의 메모리 낭비는 있을 수 있으나, 런타임 중 발생할 수 있는 오류가 없고, 성능에 큰 악영향을 주지 않는 한 성능 최적화 관점에서는 일반적으로 큰 문제가 되지 않습니다. Direct3D12는 자원 관리와 관련해서 개발자에게 많은 제어 권한을 주기 때문에, 전반적인 렌더링 파이프라인의 성능을 고려하여 적절하게 사용하는 것이 중요합니다.

질문2에 대한 답변:
예, dltmddnr05님이 이해하신 것이 맞습니다. SetGraphicsRootDescriptorTable 함수의 인자에 핸들 값을 넣어줄 때, 해당 핸들이 가리키는 위치에서부터 RootSignature에 정의된 디스크립터 범위만큼 (예시로, b0부터 b5, t0부터 t5까지 총 10개) DX가 자동으로 인식하여 해당 범위의 디스크립터들이 모두 바인딩됩니다. 따라서 디스크립터 테이블을 효율적으로 활용하려면 다음 오브젝트를 그릴 때 오프셋을 적절히 조절하여 새로운 디스크립터가 바인딩될 수 있도록 해야 합니다. 이는 디스크립터 테이블의 재사용성을 높여 성능 최적화에 기여할 수 있습니다.

두 질문 모두 세심한 이해와 설계가 필요한 부분입니다. 추가적으로 궁금하신 점이 있으시면 언제든지 질문해 주세요.

megayuchi님의 프로필 이미지
megayuchi
지식공유자

2024. 07. 13. 19:34

안녕하세요 유영천입니다. 놀랍게도 ai가 답변한 내용이 맞습니다. 말이 좀 이상하지만 어쨌든 맞긴 맞습니다. -_-

1번 질문)

바깥에서 디스크립터를 설정(CopyDescriptorSimple등을 이용)하지 않아도 쉐이더에서 해당 리소스를 억세스 하지 않는 이상,D3D런타임이나 쉐이더 코드는 그 위치(b0, t0등)의 디스크립터가 설정이되어있는지조차 알지 못합니다. 만일 이렇게 설정을 하지 않은 상태에서 쉐이더 코드에서 해당 위치(b0, t0등)를 억세스 할 경우에는 gpu쪽에서 크래시하게 됩니다.

어쨌든 쉐이더 코드에서 정말 사용하지 않는다면 문제 없습니다.

 

2) RootSignature를 전달하는 이유 자체가 해당 주소로부터 순서대로 억세스하기 위함입니다. 따라서 시작 위치와 개수를 알면 중간 원소들에 대해선 별도의 바인딩이 필요없는것이죠. 쉐이더코드 RootSignature에 적혀있는대로 시작 위치와 개수만을 무조건 믿고 처리합니다.

질문하신대로 RootSignature에서 총 10개의 레지스터를 사용하고 있다면(디스크립터 10칸) 추가되는 draw코드에선 10칸만큼(10 x DescriptorSize) 이동한 descriptor handle을 전달하면 됩니다.