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

김종수님의 프로필 이미지

작성한 질문수

삼각형의 실전! Vulkan 중급

Vulkan Pipeline dynamic state

descriptorSet에 대한 질문들

해결된 질문

24.08.05 17:18 작성

·

115

·

수정됨

0

안녕하세요?

  1. descriptorSet을 descriptorPool에서 할당 받아서 사용하는 이유가 뭔가요?


    @@@

  2. buffer와 memory에 대한 질문입니다. 예를 들면 device와 physicalDevice 처럼 buffer는 논리적인 개념이고 memory는 물리적인 개념인가요?
    @@@

  3. pipelineLayout을 생성할 때 info 구조체에 setLayoutCount 값을 설정합니다.
    pipelineLayout으로 생성하는 graphics pipeline은 1개 이고, 그 graphics pipeline을 구성하는 vtx-frm shader에는 몇 개의 uniform을 사용하는지 이미 고정되어 있는데요.
    그러면 하나의 setLayoutCount만 사용하면 될 것 같은데, setLayoutCount를 따로 설정해주는 이유가 있나요?
    @@@

  4. descriptorSet은 이런 흐름으로 생성하고 사용하는 게 맞나요?
    - descriptorSetLayout으로 그래픽스 파이프라인에서 몇 개의 uniform이 사용될지 미리 알림
    - descriptorPool로 descriptorSet을 사용 가능한 할당
    - descriptorSet을 writeDescriptorSet으로 갱신해서 cpu->gpu로 데이터를 송부하는 용도로 사용하도록 설정 (readDescriptorSet는 검색해보니 없나보네요...ㅎㅎ)
    - 미리 uniform buffer를 업데이트 (render()의 1. 위치 정보 갱신)
    - vkCmdBindDescriptorSets() 을 호출하면 갱신된 위치 정보가 gpu에도 전송됨
    @@@

    opengl에 비해 무지 어렵네요 vulkan...ㅎㅎ;;

답변 2

2

dlgmlals3님의 프로필 이미지

2024. 08. 05. 19:40

지나가다가 남깁니다.
제가 아는 내용을 대략 적어 보았는데요,
삼각형 님이 덧붙여주시면 저도 더 공부가 되고 좋을 것 같습니다.

descriptorSet을 descriptorPool에서 할당 받아서 사용하는 이유가 뭔가요?

--->

메모리 풀의 사용용도는 매번 디스크립터세트를 생성/해제하지 않고
재사용하여, 메모리 최적화를 극대화 하기 때문입니다.

물론 재 사용하지 않고 " VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT " 비트를 사용하여 개별 해제도 가능합니다.

 

@@@

buffer와 memory에 대한 질문입니다. 예를 들면 device와 physicalDevice 처럼 buffer는 논리적인 개념이고 memory는 물리적인 개념인가요?

--->

물리적인 개념이 맞습니다. 메모리를 버퍼에 바인딩을 1회 하고 그 후로는 버퍼로만 컨트롤 하게 됩니다.

cpu에서는 메모리를 할당하기 위해서 malloc을 사용하고 opengl 에서도 gralloc 을 들어보셨을 겁니다.

opengl 에서는 메모리할당을 드라이버단에서 했지만,

vulkan은 gpu 메모리 할당을 application 단에서 하도록 되어있고,

결국 gpu 메모리 할당 후 gpu/cpu 공유하는 가상주소를 가져와서 write를 하는 방식이 되겠습니다.

 

@@@

pipelineLayout을 생성할 때 info 구조체에 setLayoutCount 값을 설정합니다.

pipelineLayout으로 생성하는 graphics pipeline은 1개 이고, 그 graphics pipeline을 구성하는 vtx-frm shader에는 몇 개의 uniform을 사용하는지 이미 고정되어 있는데요.

그러면 하나의 setLayoutCount만 사용하면 될 것 같은데, setLayoutCount를 따로 설정해주는 이유가 있나요?

-->

하나의 디스크립터 세트 레이아웃을 사용하고,

셰이더에서 binding 변수만 맵핑 하여 사용해도 되지만, set 변수도 활용하여 같은 속성인 경우 묶을수가 있습니다.

매터리얼의 속성이 여러개인 경우 같은 속성의 여러개의 디스크립터 세트를 만들어서 또 그 안에서 바인딩으로 할당 할수도 있습니다.

아래 예제를 보시면, 돌의 재질을 만들때 여러개의 디스크립터 세트를 사용하는 예제가 있으니 참고하시면 되겠습니다.

https://web.engr.oregonstate.edu/~mjb/vulkan/Handouts/DescriptorSets.1pp.pdf

 

@@@

descriptorSet은 이런 흐름으로 생성하고 사용하는 게 맞나요?

- descriptorSetLayout으로 그래픽스 파이프라인에서 몇 개의 uniform이 사용될지 미리 알림

---> count 뿐 아니라, 해당 리소스의 타입 용도등을 설정 해야 합니다.

- descriptorPool로 descriptorSet을 사용 가능한 할당

- descriptorSet을 writeDescriptorSet 으로 갱신해서 cpu->gpu로 데이터를 송부하는 용도로 사용하도록 설정 (readDescriptorSet는 검색해보니 없나보네요...ㅎㅎ)

--> 생성한 디스크립터 세트와 생성한 버퍼를 연결해주신다고 생각하시면 됩니다.

.dstBinding 내부 변수의 값도 잘 확인하시면 되겠습니다.

- 미리 uniform buffer를 업데이트 (render()의 1. 위치 정보 갱신)

- vkCmdBindDescriptorSets() 을 호출하면 갱신된 위치 정보가 gpu에도 전송됨

--> 커맨드 버퍼에 디스크립터 세트를 바인딩 합니다.

위치 정보가 gpu에 전송된다는 의미도 맥락에서 맞지만, 바인딩이란 의미를 생각해보시면 좋을 것 같습니다.
opengl 사용하실때도 버퍼나 이미지를 바인딩을 해야 사용 하실 수 있는 것과 비슷한 개념입니다.

추가로 위 함수는 초기화 과정이 아니라, 렌더링 할 때 호출해야 됩니다.

@@@

1

삼각형님의 프로필 이미지
삼각형
지식공유자

2024. 08. 06. 09:43

안녕하세요? 김종수님,

벌칸이 조금 어렵죠? ㅎㅎ 그래도 자주 접하시다보면 익숙해지실 꺼에요.

파이팅입니다.

 

  1. descriptorSet을 descriptorPool에서 할당 받아서 사용하는 이유가 뭔가요?

    멀티 쓰레드를 보장하기 위함인데요. VkDescriptorPool을 쓰레드마다 생성해서 동기화 객체 없이 VkDescriptorSet을 할당 받기 위함입니다. 커맨드풀도 동일한 이유입니다.


  2. buffer와 memory에 대한 질문입니다. 예를 들면 device와 physicalDevice 처럼 buffer는 논리적인 개념이고 memory는 물리적인 개념인가요?

    메모리도 논리적인 개념입니다. 메모리의 물리적인 개념은 DRAM, VRAM이죠. 메모리도 버퍼와 같은 리소스라고 생각하시면 됩니다. 버퍼와 메모리를 따로 나눈 이유는 메모리 할당이 매우 무거운 작업이기 때문입니다. 메모리를 한번 할당하고 버퍼를 생성했다 파괴했다하면서 재활용하는게 더 효율적이거든요.

  3. pipelineLayout을 생성할 때 info 구조체에 setLayoutCount 값을 설정합니다.
    pipelineLayout으로 생성하는 graphics pipeline은 1개 이고, 그 graphics pipeline을 구성하는 vtx-frm shader에는 몇 개의 uniform을 사용하는지 이미 고정되어 있는데요.
    그러면 하나의 setLayoutCount만 사용하면 될 것 같은데, setLayoutCount를 따로 설정해주는 이유가 있나요?

    파이프라인 레이아웃을 어떻게 구성할지는 개발자의 몫입니다. 셋을 하나만 사용해도 되고 여러개 사용해도 됩니다. 하지만 목적에 따라 셋을 여러개 사용하는게 좋습니다. 이건 좀 더 벌칸을 이해해야지 이해할 수 있는 내용인데요. 지금 당장 이해가 되지 않더라도 이런 경우가 있을 수 있구나라고 읽고 넘어가셔도 됩니다. 셋에다가 리소스를 바인딩하기 위해서는 디스크립터 셋이 필요합니다. 디스크립터 셋에 리소스를 바인딩하는 작업은 매우 무거운 작업입니다. 렌더링을 할 때, 라이팅과 카메라는 장면을 렌더링할 때 모두 동일해서 한번만 업데이트 하면 됩니다. 하지만 오브젝트의 위치는 오브젝트마다 업데이트가 되어야합니다. 이런 경우에 셋을 하나만 사용하면 업데이트가 필요하지 않은 라이팅과 카메라까지 업데이트를 해야합니다. 그럼 업데이트양이 많아서 성능이 느려지겠죠? 라이팅과 카메라를 위한 첫번째 셋, 오브젝트를 위한 두번째 셋을 구분한다면 업데이트를 최소화해서 성능을 높힐 수 있습니다.

  4. descriptorSet은 이런 흐름으로 생성하고 사용하는 게 맞나요?
    - descriptorSetLayout으로 그래픽스 파이프라인에서 몇 개의 uniform이 사용될지 미리 알림
    - descriptorPool로 descriptorSet을 사용 가능한 할당
    - descriptorSet을 writeDescriptorSet으로 갱신해서 cpu->gpu로 데이터를 송부하는 용도로 사용하도록 설정 (readDescriptorSet는 검색해보니 없나보네요...ㅎㅎ)
    - 미리 uniform buffer를 업데이트 (render()의 1. 위치 정보 갱신)
    - vkCmdBindDescriptorSets() 을 호출하면 갱신된 위치 정보가 gpu에도 전송됨

    dlgmlals3 님이 잘 설명해 주셨습니다.