주의 : 답이 틀릴 수도 있습니다. 그냥 정리하는 용도로 올립니다. 혹시라도 도움이 필요한 분이 있다면 도움이 되었으면 좋겠네요.

경고 : 숙제하려고 베끼는 데 사용하지 마십시오. 본인의 미래를 망칠 뿐입니다. 나중에 저를 원망하지 마세요.

부탁 : 문제 풀이가 잘못되었으면 지적해 주셨으면 좋겠습니다.



수직으로 세운 막대 끝에 연결된 끈에 질량이 m 인 물체를 매달고, 중심축을 중심으로 막대를 돌려 물체를 회전시킨다고 하다. 막대 축으로부터 물체까지의 거리가 D 이고, 물체의 빠르기는 v0 이다. 끈의 질량을 무시한다고 할 때,



(a) 물체에 작용하는 알짜힘은 어느 방향을 향하는가?

(b) 물체에 작용하는 알짜힘의 세기를 구하라.

(c) 끈에 작용하는 장력 세기는 얼마인가?


일단 문제에서는 등속 원운동을 가정하지 않았지만, 등속 원운동이라 생각하고 문제를 풀겠습니다.


일정한 속도로 등속 원운동을 한다면, 속도의 크기( 빠르기 )와 가속도의 크기는 다음과 같습니다. 증명은 [ 연습문제 5-5 ] 에서 확인하십시오.


식 1 에서 ω 는 각속도입니다.


식 1.


( a )


등속 원운동 시에 힘의 방향은 막대의 중심축을 향하게 됩니다. 


여기에서 헷갈리는 건, 알짜힘을 구하는 과정을 서술하라는 것인지, 아니면 중력에 의한 등속 원운동과 끈을 매달고 회전시켰을 때의 등속 원운동이 같은 개념이라는 가정을 깔고 문제를 풀라는 것인지 알 수가 없습니다.


이미 증명은 [ 연습문제 5-5 ] 에서 했으므로 따로 하지는 않겠습니다. 결국 중력이라는 가상의 끈으로 이어져 있든지 아니면 실제 끈으로 이어져 있든지 나타나는 결과는 같습니다.


( b )


식 1 을 통해 물체의 가속도를 알 수 있기 때문에, 알짜힘 크기는 다음과 같습니다.


식 2.


( c )


문제에서는 중력에 대해서 언급하고 있지 않지만 실제 해답에서는 중력을 고려하고 있습니다. 그래서 이 문제 풀이에서 오답이 나왔습니다. 만약 중력이 작용하지 않으면 T = F 가 되겠죠.


하지만 중력을 고려해야 하므로 물체에는 알짜힘과 중력의 합의 크기가 장력의 크기와 같습니다.


그림 1.


피타고라스 정리를 통해 문제를 풀어 보겠습니다.


식 3.


하지만 해답은 다음과 같습니다.


식 4.


해답이 오답인 것 같습니다.

원문 : Vulkan Debug Utilities.

주의 : 허락받고 번역한 것이 아니므로 언제든 내려갈 수 있습니다.

주의 : 번역이 개판이므로 이상하면 원문을 참고하세요.


Introduction

벌칸 API 는 이제 2 살이 되었습니다. 그리고 다른 것들처럼 개량할 영역이 있어 보입니다( and as with all things it is showing areas that require improvement ). 디버깅이 그런 영역 중의 하나인데요, 여기에서 우리는 벌칸 커뮤니티를 위해 큰 이득을 제공해줄 작은 변화를 줄 수 있습니다. IHV( 역주 : Independent Hardware Vendor ) 들과 몇몇 게임 회사들로부터의 입력을 요청하고 깃허브 유저들로부터 피드백을 받은 후에, 우리는 VK_EXT_debug_report 와 VK_EXT_debug_marker 에 의해 노출되는 디버깅 기능들을 개선하기로 했습니다. 우리가 연구한 결과, 현재 익스텐션( extension )에 다가 새로운 기능을 억지로 집어 넣으려고 시도하는 대신에, 익스텐션을 교체하는 것이 올바른 결정이라고 판단했습니다. 그 변화는 새로운 익스텐션인 VK_EXT_debug_utils 의 창조를 이끌었습니다.

Why the New Extension?

Vulkan Working Group 은 몇몇 소프트웨어 회사들에 근무하는 개발자들로부터 각각의 디버그 메시지들로부터 더 많은 정보를 받아 자신들의 코드에서 유발점( trigger )을 구별( isolate )할 수 있도록 해 달라는 피드백을 받았습니다. 애플리케이션은 다중의 벌칸 오브젝트들을 생성하고 그 중의 하나만이 잘못 다뤄질 수 있기 때문에, Validation messages created a special concern.

소프트웨어 개발자들이 더 효율적으로 이슈( issue )들을 구별하는 것을 돕기 위해, LunarG 는 VK_EXT_debug_report 와 VK_EXT_debug_marker 의 기능들을 병합해 더욱 유용한 디버그 메시지들을 생성하기로 했습니다. 그러나 이 두 가지 개별 익스텐션들 사이에서 협업을 시도하는 중에, 우리는 근본적인 문제가 있다는 것을 깨닫게 되었습니다. VK_EXT_debug_report 는 인스턴스( instance ) 익스텐션이지만 VK_EXT_debug_marker 는 디바이스( device ) 익스텐션이라는 겁니다. 디바이스 익스텐션에 대해 독립적인 인스턴스 익스텐션의 기능을 지정하기 위한 쉽고 깔끔한 방법이 존재하지 않습니다. 단순함을 위해, 그냥 새로운 익스텐션을 만들고, 한 곳에서 필수적인 모든 아이템들을 지원하기로 했습니다.

또한 유저의 디버그 콜백에 반환되는 정보를 확장하기도 했습니다. 이러한 변경은 예전의 익스텐션에도 적용될 수 있었지만, 대부분의 구조체들의 pNext 체인에 아이템들을 추가할 것을 요구했습니다. 그렇게 할 수는 있었지만, 우리가 생각한 것보다는 더 복잡했습니다. 왜냐하면 모든 디버그 콜백이 pNext 체인을 고려해야만 하기 때문이었습니다. 물론 우리는 여전히 나중에는 pNext 체인에 기능을 추가하긴 할 겁니다.

마지막으로 VK_EXT_debug_report 익스텐션은 VkDebugReportObjectTypeEXT 라는 특별한 내부 열거형을 사용해서 오브젝트 타입( type )을 추적( tracking )합니다. 이 열거형은 잠깐 동안 지원되었으며 심지어는 VK_EXT_debug_marker 익스텐션에서도 사용되었습니다. 하지만 벌칸 명세의 최신 버전들에서는 이 구조를 새로운 코어 오브젝트 타입 열거형으로 대체했습니다. 명세가 변경되었으므로, 크로노스는 VkDebugReportObjectTypeEXT 를 확장하는 것을 중지하고 대신에 VkObjectType 에다가만 새로운 열거을 추가하는 것을 지원하기로 결정했습니다. 결과적으로 VkDebugReportObjectTypeEXT 열거형은 시간이 흐르면 점점 더 곰팡내나게 될 것입니다.

이러한 사실들을 고려해서, LunarG 는 벌칸 디버그 유틸리티를 처음부터 새로 만들기로 했습니다.

Benefits of This New Extension

VK_EXT_debug_utils 는 VkDebugUtilsMessengerEXT 라는 디버그 메신저( messenger ) 개념을 소개합니다. 이를 생성하는 동안에, 애플리케이션은 어떤 디버그 메시지 타입들과 심각성( severity )들이 필요한지를 세부적으로 결정합니다. 추가적으로, 애플리케이션은 콜백 메시지 핸들러에 대한 함수 포인터를 제공하는데, 이는 메시지가 적절한 심각성과 타입을 만족시켰을 대 호출될 것입니다. VkDebugReportCallbackEXT 오브젝트 타입은 VK_EXT_debug_report 와 유사한 방식으로 동작합니다. 개선된 유용상은 새로운 콜백에 이제는 데이터가 공급된다는 데 있습니다. 이 콜백에서 공급된 데이터를 읽기 위해서는 "Creating a Debug Messenger Callback" 섹션을 참고하십시오.

VK_EXT_debug_marker 익스텐션과 마찬가지로, 새로운 익스텐션은 VkCommandBuffer 의 특정 위치를 식별할 수 있도록 해 줍니다. 이전에 VK_EXT_debug_marker 에서는, 실별된 위치가 "마커( marker )"라고 불렸습니다. 이제 VK_EXT_debug_utils 에서는, 그것들이 "레이블( label )"이라 불립니다. 또한 Vk_EXT_debug_utils 는 이 레이블들을 VkQueue 에다가 삽입해서 벌칸 큐( queue )에서 처리중인 runtime/driver/hardware 의 프로그레스를 식별할 수 있도록 하는 기능을 추가했습니다. 레이블에 대한 더 많은 정보를 원한다면 "Adding Labels" 섹션을 참고하십시오.

VK_EXT_debug_utils 익스텐션에 의해서 지원되는 VK_EXT_debug_marker 의 또 다른 기능은 애플리케이션이 정의한 데이터를 벌칸 핸들과 연관시키는 기능입니다. 이 기능의 거의 대부분의 용도는 각 벌칸 핸들을 쉽게 식별이 가능한 문자열 이름으로 만드는 것입니다. 벌칸 오브젝트의 핸들값은 로더( loader ), 레이어( layer ), ICD 를 포함한 모든 벌칸 컴포넌트에 대해서 내부적으로 변할 수 있습니다 -- 그러므로 핸들을 명명하지 않으면, 반환된 정보들이 맞는지 헷갈릴 겁니다. 예가 하나 있습니다:

만약 vkCmdBindPipeline 을 잘못 호출했고 validation 레이어를 활성화해 둔 상태라면, 에러 메시지가 에러가 있는 VkCommandBuffer 를 위한 핸들에 대해 언급하는 것을 찾을 수 있을 것입니다. 그런데 VkCommandBuffer 핸들에 대한 여러분의 리스트에서 문제가 있는 핸들을 찾으려고 하면, 어떤 값도 일치하는 것이 없습니다. 그것은 로더나 레이어에 의해서 발생할 수 있는 일입니다. 왜냐하면 그것들은 같은 오브젝트에 대해서 다른 핸들을 가지고 있기 때문입니다.

그러나 애플리케이션이 자신의 벌칸 핸들에 대한 이름을 설정해 놓았다면, 그 이름들은 이 익스텐션을 지원하는 모든 컴포넌트들 내부에서 그 핸들들과 연관됩니다. 이는 오브젝트에 대한 핸들값이 변경되었더라도 올바로 동작합니다. 위의 경우에, VkCommandBuffer 가 "Primary Command Buffer in Thread B" 라고 명명되어 있었다면, 여러분은 특이한 핸들 값을 획득하게 되지만, 그것은 "Primary Command Buffer in Thread B" 라는 이름을 가지고 있을 것입니다. 이름에 대한 더 많은 정보를 원한다면, "Naming Objects" 섹션을 참고하십시오.

VK_EXT_debug_utils 는 태그를 사용하여 특정 오브젝트를 위한 바이너리( binary ) 칸텐트를 정의하는 기능을 계속해서 지원합니다. 이러한 태그가 걸린 칸텐트는 매우 복잡한 경향이 있으며, 거의 대부분 RenderDoc 같은 부가적인 칸텐트를 필요로 하는 디버깅 레이어를 위해서 사용됩니다. 태그들은 어떠한 validation 레이어 메시지에 의해서도 사용되지 않습니다. 그리고 디버그 메신저 콜백에서 유저가 획득할 수도 없습니다. 더 많은 정보를 원한다면 "Tagging Objects" 섹션을 참고하십시오.

위의 정보들을 일고 나면, 여러분은 새로운 익스텐션이 별로 새로운 것을 포함하고 있지 않다고 느낄 것입니다. 그러나 VK_EXT_debug_report 에 등록된 콜백에서 반환된 데이터를 살펴 본다면, 디버그 메시지가 콜백에 반환될 때 단지 하나의 오브젝트와 메시지만을 획득하게 된다는 것을 깨닫게 될 것입니다. 새로운 익스텐션을 사용하고 있다면, VK_EXT_debug_utils 는 여러분의 콜백 함수에 설정하고 넘김수 있는 모든 정보들을 결합합니다. 여기에 이전의 VK_EXT_debug_report 익스텐션이 반환한 콜백 메시지와 더불어 더 포함된 추가 정보들을 정리해 봤습니다:

  • 각 디버그 메시지와 관련이 있는 오브젝트들의 리스트.
  • ( 만약 이름이 설정되었다면 ) 각 오브젝트와 연관된 이름.
  • 해당 시점까지 맞닥뜨린 커맨드 버퍼 레이블 리스트.
    • 오브젝트 리스트에서 VkCommandBuffer 만이 존재하고 그것과 관련이 있는 레이블을 가지고 있을 때만...
  • 해당 시점까지 맞닥뜨린 큐 레이블 리스트.
    • 오브젝트 리스트에 VkQueue 만이 존재하고 그것과 관련된 이름을 가지고 있을 때만...

이 부가 정보들을 사용하면, 가장 복잡한 애플리케이션이라고 할지라도, 디버그 메시지의 위치를 쉽게 좁혀갈 수 있을 것입니다. 이는 VK_LAYER_LUNARG_standard_validation 을 활성화했을 때 특히 유용하며, 일련의 특별한 커맨드들에 대한 validation 메시지로부터 에러를 받게 될 것입니다.

How Do I Use It?

사용하기 전에, VkEnumerateInstanceExtensionProperties 를 사용해서 VK_EXT_debug_utils 익스텐션을 사용할 수 있는지 확인해야 합니다. 그러나 일단 익스텐션이 이용가능하다는 것을 확인했다면, 그것의 디버깅 기능들을 해제할 수 있습니다.

우리는 아래에서 VK_EXT_debug_utils 의 핵심 기능들에 대해서 다룰 겁니다. 하지만 이 새로운 익스텐션을 사용하는 방법은 벌칸 명세의 "Debugging" 섹션에서 자세하게 알아 볼 수 있을 것입니다.

이 익스텐션을 사용하는 것은 이전에 VK_EXT_debug_report 와 VK_EXT_debug_marker 를 사용하는 것과 유사합니다. 그러나 두 개의 익스텐션을 개별적으로 활성화하는 대신에( 하나는 인스턴스 익스텐션, 하나는 디바이스 익스텐션 ), 여럽분은 하나의 인스턴스 익스텐션만을 활성화하면 됩니다.

먼저 새로운 익스텐션을 사용해 디버그 메시지를 받는 것부터 살펴 보겠습니다. 만약 디버그 메시지가 필요하지 않다면, "Naming Objects" 섹션으로 바로 넘어 가십시오.

Creating a Debug Messenger Callback

디버그 메시지를 받겠다고 했으므로, 먼저 콜백 함수를 생성해야 합니다. 그것은 디버그 메시지를 받으며 PFN_vkDebugUtilsMessengerCallbackEXT 함수 포인터의 형태로 되어 있어야 합니다.

새로운 콜백에서는 메시지 심각성( messageSeverity ) 가 메시지 타입( messageType )과 분리되었음을 알아채게 될 것입니다. 심각성은 메시지의 중요도를 지정합니다. 가능한 값들은 현재 다음과 같이 정의되어 있습니다:

메시지의 중요도가 올라갈수록, 열거형 값도 올라갑니다. In addition, we've left space for future types that could fit in between any of the existing values. 그런 이유로, 여러분은 콜백에서 항상 값들을 비교할 수 있습니다.

메시지 타입은 여러분이 받고 있는 메시지의 종류를 기술합니다. 현재 다음과 같은 메시지 타입들을 이용할 수 있습니다( 하지만 나중에 더 추가될 수 있습니다 ):

범용( General ) 메시지는 일반적으로 벌칸 컴포넌트 자체에서 옵니다. Vadiation 비트는 애플리케이션의 행위를 명세에 대해 검증하는 과정과 관련이 있는 메시지를 가리킵니다. 이것들이 validation 레이어로부터 오는 가장 일반적인 메시지들입니다. 왜냐하면 거의 대부분의 validation 에러나 경고들은 벌칸 명세를 위해발 수 있음을 가리키기 때문입니다. 마지막으로, 애플리케이션의 성능을 개선할 것을 제안하는 성능( performance ) 메시지들이 있습니다.

pCallbackData 는 VkDebugUtilsMessengerCallbackDataEXT 구조체를 가리키는데요, 이는 메시지를 유발한 것이 무엇인지에 대한 정보를 포함하고 있으며, 메시지가 발생된 위치를 찾아내는 데 충분히 도움을 줍니다 : 

구조체의 처음 세 개의 파라미터( parameter )들은 대부분의 벌칸 구조체에서 동일합니다. 그래서 그것에 대해서 여기에서 다루지는 않겠습니다.

두 번째 세 개의 파라미터들은 특정 메시지에 대한 모든 세부사항을 제공합니다.

  1.  pMessageIdName 은 문자열인데, 메시지를 유발한 것이 무엇인지를 가리킵니다. Validation 레이어의 경우, 이 문자열은 VUID( valid usage ID ) 문자열 식별자를 포함할 것입니다. 그것은 그 레이어가 위반했다고 생각하는 명세의 특정 위치를 식별하는 데 도움이 됩니다.
  2. messageIdNumber 는 ( 0 이 아니라면 ) 이 메시지에 대한 고유 번호를 가리킵니다. 만약 메시지가 validation 레이어로부터 발생했다면, 그것은 발생한 경고나 에러를 위한 고유 숫자 VUID 를 포함할 것입니다. 이 숫자를 레이어가 위반이 발생했다고 생각하는 벌칸 명세의 위치를 찾기 위한 테이블의 색인으로 사용하십시오.
  3. pMessage 는 ( null 종료 ) C 스타일 문자열입니다. 이는 메시지의 세부사항을 가리킵니다.

콜백은 메시지 ID 번호와 이름을 모두 반환합니다. Validation 레이어들은 현재 주어진 validation 메시지를 위해 messageIdNumber 를 반환합니다. 만약 messageIdNumber 가 제출되었다면, 여러분은 실제 Valid Usage ID 문자열을 vk_validation_error_messages.h 헤더 파일에 접근해서 검색할 수 있습니다. UNIQUE_VALIDATION_ERROR_CODE 열거형에서 값을 찾아서, VUID 를 명세 정보( spec snippet ) 매핑하는 테이블에서 값을 찾으면 됩니다. 명세 정보는 최종 VUID 문자열을 포함하는데요, 이는 명세에서 정확한 섹션을 찾아내기 위해서 사용될 수 있습니다. 우리는 이게 유저에게는 복잡한 작업이라는 것을 깨달았으며, 그래서 앞으로, Validation 레이어들은 새로운 pMessageIdName 필드를 사용해 실제 명세 VUID 문자열을 반환하도록 하는 것을 의도하고 있습니다.

일단 VUID 문자열을 획득했다면, 벌칸 명세를 열어서 해시 심볼( # ) 뒤에 VUID 문자열을 붙이면 그 섹션으로 바로 갈 수 있습니다.

예를 들어 :

VUID 문자열이 다음과 같다고 하면 :

VUID-VkApplicationInfo-pApplicationName-parameter

여러분은 스펙 섹션에 다음과 같이 직접 접근할 수 있습니다:

https://www.khronos.org/registry/vulkan/specs/1.1/html/vkspec.html#VUID-VkApplicationInfo-pApplicationName-parameter

이제 이 익스텐션에서 새로운 아이템들을 살펴 봅시다. queueLableCount 와 pQueueLables 는 애플리케이션이 VkQueue 에다가 적용한 레이블에 대한 정보를 포함합니다. 이 필드들은 VkQueue 오브젝트가 pObjects 리스트에 포함되었을 때만 활성화됩니다. pQueueLables 는 메시지가 발생한 시점까지 특정 VkQueuObject 에서 설정된 레이블들만을 포함합니다. 이 레이블들은 다음과 같은 정보를 포함합니다:

pLabelName 은 애플리케이션이 정의한 레이블의 이름이며 color 는 여러분이 설정한 부동소수점 색상입니다. Validation 레이어들과 디버그 메시지들이 색상을 사용하지는 않지만, 다른 레이어들이나 여러분의 애플리케이션은 이 정보를 사용할 수도 있습니다.

만약 VkQueue 오브젝트가 pObjects 리스트에 없다면, queueLabelCount 는 0 이고 pQueueLabels 는 null 이어야 합니다. pQueueLabels 배열의 아이템들은 정렬되어 있어서 가장 최근의 레이블이 낮은 인덱스 값에 들어 가 있습니다. 그러므로 0 번 인덱스에 있는 레이블이 VkQueue 와 연관된 가장 최근의 레이블입니다.

이와 유사하게 cmdBufLabelCount 와 pCmdBufLabels 는 pObjects 리스트에 있는 VkCommandBuffer 로부터의 모든 레이블들을 포함합니다. 레이블들은 세컨더리( Secondary ) 커맨드 버퍼에 의해 프라이머리( Primary ) 커맨드 버퍼로부터 상속될 수 있습니다. 그러나, 디버그 메시지의 경우에는, 거의 대부분의 레이어들과 로더는 단지 활성화된 커맨드 버퍼나 그것의 자식 오브젝트들에 대한 정보만을 알고 있습니다. 그러므로, VkCommandBuffer 가 pObjects 에 있고 VkCommandBuffer 가 연관된 레이블을 가지고 있다면, cmdBufLabelCount 는 0 이 아닌 값이며 pCmdBufLabels 는 null 이 아닌 값입니다.

VkDebuUtilsMessengerCallbackDataEXT 의 마지막 두 개의 요소는 objectCount 와 pObjects 입니다. pObjects 는 메시지와 쉽게 연관될 수 있는 모든 오브젝트들에 대한 정보를 포함합니다. 그 정보는 VkDebugUtilsObjectNameInfoEXT 구조체에 저장됩니다.

pObjects 내의 각 오브젝트들은 오브젝트의 타입( objectType ) 과 오브젝트의 핸들( objectHandle ) 을 가지고 있습니다. 만약 ( "Naming Objects" 섹션에서 설명하는 것처럼 ) 오브젝트를 위한 이름을 지정한다면, 오브젝트의 이름( pObjectName ) 이 여러분이 제공한 이름을 포함하는 문자열에 대한 포인터로 설정될 것입니다 -- 여러분이 거의 대부분의 오브젝트들을 쉽게 식별할 수 있게 해 줍니다. pObjects 를 레이블과 함께 사용하면, 여러분은 메시지를 발생시킨 코드의 위치를 좁힐 수 있을 겁니다.

마지막으로, 콜백 함수는 유저가 제공한 데이터( pUserData ) 를 받을 수 있습니다. 그것은 메신저를 생성할 때 각 메신저에 제공한 것입니다.

Creating ( and Destroying ) a Debug Messenger

콜백을 설정하고 나면, 디버그 메신저를 생성할 필요가 있습니다. 그것은 메시지가 발생할 때 콜백을 호출하기 위해서 사용될 것입니다.

이 역시 여러분이 벌칸 작업을 하면서 봤던 매우 표준적인 외형을 가졌습니다. 가장 중요한 컴포넌트는 2 번째 파라미터인 pCreateInfo 입니다. 이는 다음과 같은 구조체에 대한 포인터입니다:

messageSeverity 파라미터는 콜백을 호출하기를 원하는 모든 메시지 심각성들을 지정하기 위한 것입니다. 여러분은 "플래그 비트( FlagBit )" 가 아니라 "플래그들( flags )"이 사용된다는 것을 알아차렸을 겁니다. 왜냐하면 이것은 하나 이상의 값들을 취하기 때문입니다. 예를 들어 다음과 같이 메시지 심각성들을 설정할 수 있습니다: 

마찬가지로 messageType 은 여러분이 추적하고자 하는 모든 메시지 타입들의 조합입니다. 그리고 나서 pfnUserCallback 을 위에서 생성한 콜백 함수에 대한 포인터로 설정합니다.

여러분의 콜백에 반환되는 메시지들은 반드시 여러분이 활성화한 심각성과 vkCreateDebugUtilsMessengerEXT 호출 동안 활성화한 타입이어야만 합니다.

그렇지 않다면, 만약 신각성은 일치하는데 타입은 일치하지 않는다든가 한다면, 콜백이 호출되지 않을 것입니다.

마지막으로 여러분은 pUserData 를 사용해서 부가적인 데이터에 대한 포인터를 제공하거나 그것을 null 로 설정할 수 있습니다. 로그를 출력한다든가 하는 작업을 수행하기 위해서, 콜백이 호출되는 동안에 애플리케이션이 구조체나 클래스에 대한 포인터를 사용하는 경우가 많습니다.

모든 표준 벌칸 오브젝트들처럼, VkDebugUtilsMessengerEXT 를 vkDestroyDebugUtilsMessengerEXT 를 호출해서 파괴하게 됩니다.

Naming Objects

네이밍은 애플리케이션이 특정 이름으로 오브젝트를 식별할 수 있도록 해 주며, 오브젝트 핸들 값이 로더, 레이어, 심지어는 런타임에 들어갈 때 변경될 수 있기 때문에 유용합니다. 만약 메시지가 특정 오브젝트를 위해 그런 레이어 중 하나에서 발생했다면, 그 핸들은 유저가 알지 못하는 값이 될 것이며 혼란스럽게 만들 것입니다. 그러므로 오브젝트를 네이밍하는 기능이 생겼습니다.

왜 네이밍이 유용한지 빠르게 살펴 봅시다. 여러분이 validation 레이어에 의해 검출된 잘못된 호출을 만드는 애플리케이션을 가지고 있다고 합시다. 또한 벌칸 로더는 오브젝트 자체를 래핑( wrapping )하고 있으며, 그래서 그것은 오브젝트와 연관된 다른 데이터를 유지할 수 있다고 합시다. 애플리케이션에서는 오브젝트에 대해  0xFEED 라는 핸들을 가지고 있습니다. 그러나 로더는 그 정보를 언랩( uwrap )해서 첫 번째 레이어에 0xF00D 라는 핸들을 넘기고 있습니다.  또한 그 레이어는 그것을 언랩해서 이제 0xBEEF 가 되었습니다. 최종적으로, validation 레이어는 버그를 발견하고 ( 여러분의 Debug Utils Messenger callback 을 사용해 ) 여러분에게 0xBEEF 가 잘못되었다고 알려 줍니다. 하지만 여러분은 0xBEEF 라는 오브젝트가 뭔지 궁금하겠죠?

자, 오브젝트에 어떤 유용한 이름을 부여했다면, 그것은 식별하기 쉬워질 겁니다. 위의 예제로 다시 돌아가 보죠. 여러분이 함수를 호출하기 전에, "Hamburger" 라는 이름을 0xFEED 와 연관된 오브젝트에 부여합니다. 만약 로더가 버그를 만나면, 여러분은 0xF00D 라는 것을 핸들로 받게 될 것입니다. 하지만 이름은 "Hamburger" 죠. 만약 레이어중 하나가 버그를 만나서, 여러분이 0xBEEF 를 받는 다고 해도 그것은 "Hamburger" 입니다. 명확하게도 네이밍이 훨씬 더 유용합니다.

VK_EXT_debug_utils 를 사용해 오브젝트를 네이밍하는 것은 VK_EXT_debug_marker 를 사용해서 오브젝트를 네이밍하는 것과 유사합니다. 그냥 다음 함수를 호출하기만 하면 됩니다 :

그 구조체는 VK_EXT_debug_marker 익스텐션에 있는 VkDebugMarkerObjectNameInfoEXT 와 유사합니다. 중요한 차이는 단순히 멤버 이름이 다르다는 것과 새로운 VkDebugUtilsObjectNameInfoEXT 구조체에서의 타입은 VkDebugReportObjectTypeEXT 열거형이 아니라 VkObjectType 열거형을 사용한다는 사실입니다 이것은 "Creating ( and Destroying ) a Debug Messenger" 에서 설명했던 콜백에 반환되는 정확히 같은 구조체입니다. 하지만 포맷을 확인할 수 있게 여기에서 다시 언급하도록 하겠습니다 :

Tagging Objects

태깅은 네이밍과 유사합니다. 하지만 매우 다른 목적을 가지고 있습니다. 네이밍의 경우에는 애플리케이션이 제공하는 문자열을 특정 오브젝트와 연관시킵니다. 하지만 태깅의 경우에는 정수 ID 와 바이너리 데이터를 오브젝트와 연관시킵니다. 태깅의 가장 잘 사용하려면, 애플리케이션과 레이어 혹은 런타임이 ID 및 데이터의 용례에 대해서 반드시 서로 동의하고 있어야 합니다.

태깅의 예는 다음과 같습니다:

  • 셰이더 오브젝트를 인간이 인식할 수 있는 버텍스 및 프레그먼트 셰이더 칸텐츠로 태깅함.
  • 버퍼를 그 칸텐츠에 대한 칸텐츠나 메타 데이터로 태깅함.

일반적으로, 거의 대부분의 디버그 레이어들과 툴들은 단순히 오브젝트를 이름으로 식별함으로써 그것들이 필요로 하는 필수 정보들을 획득합니다. Debug Utils Messenger 콜백들은 애플리케이션에 반환되기 때문에, 고유 오브젝트를 추적하기 위한 이름을 제외하고는 레이어들을 통해 넘길 필요가 있는 데이터들을 가지고 있지 않습니다. 애플리케이션은 이미 그것이 필요로 하는 모든 정보들에 대한 소유자( keeper )입니다. 그래서 Debug Utils Messenger 콜백을 통해 반환되는 태깅 정보는 존재하지 않습니다.

그러나, 여러분이 태깅을 필요로 한다면, VK_EXT_debug_utils 는 VK_EXT_debug_marker 와 비슷한 방식으로 구현을 합니다. 이 경우에, 여러분은 다음 함수를 호출하게 됩니다:

그 구조체는 VK_EXT_debug_marker 익스텐션에 있는 VkDebugMarkerObjectTagInfoEXT 와 유사합니다. 두 개의 차이점이 존재합니다 : 1) 멤버 이름들이 다름 2) VkDebugUtilsObjectNameInfoEXT 구조체의 타입들이 VkDebugResportObjectTypeEXT 열거형 대신에 VkObjectType 열거형을 사용함:

여러분 중 일부는 이 구조체에 익숙하지 않을 것니다. 그래서 간단하게 다루도록 하겠습니다. objectType 과 objectHandle 은 네이밍의 경우와 정확히 동일합니다. tagName 은 이 태그를 위한 수치 이름이나 식별자이며, 태깅되는 데이터의 유형을 식별하는 데 사용됩니다. 만약 이 정보를 가로채기 위해서 레이어를 구현한다면, 이 값은 식별되는 오브젝트를 설정하려고 시도하는 특정 정보를 가리키고 있을 것입니다. pTag 는 tagSize 바이트의 데이터에 대한 포인터인데, 이는 이 오브젝트와 연관됩니다.

Adding Labels

가끔 어떤 오브젝트가 문제가 되는지를 알아내는 것으로도 부족한 경우가 있습니다. 보통 프레임 전반에서 유사한 방식으로 오브젝트를 여러 번 손댈 수 있습니다. 이런 경우에, 여러분이 어떤 프레임에서 ( 혹은 심지어는 여러 프레임들에서 ) 문제가 발생했는지 좁힐 수 있다면 훌륭할 것입니다 -- 고속도로의 옆쪽에 거리 표지판( mile-marker )이 여러분이 어디쯤 왔는지 알 수 있게 해주는 방법과 비슷합니다.

VK_EXT_debug_utils 를 사용하면, VkQueue 나 VkCommandBuffer 에다가 레이블을 삽입할 수 있습니다. VK_EXT_debug_marker 익스텐션에 의해서 처음 노출된 "markers" 와 유사합니다 -- 그것은 VkCommandBuffer 오브젝트에만 마커들을 추가할 수 있다는 차이는 있습니다.

레이블을 VkQueue 나 VkCommandBuffer 에다가 추가하는 두 가지 방법이 존재합니다:

  • 레이블 영역( region )을 시작하고 끝내기.
  • 그냥 레이블 삽입하기.

어떻게 사용하는지 이해하기 위해서 빠르게 예제를 살펴 봅시다.

여러분이 인간형 모양을 그리고 있다고 합시다. 다음과 같은 방식으로 그릴 겁니다:

Validation 을 실행할 때, 여러분은 드로( draw )에서 에러를 발견했다고 합시다. 하지만 어떤 드로가 문제인지 좁힐 수 있을까요? 레이블을 사용하면, 다음과 같이 할 수 있습니다.

begin/end 와 insert 는 모두 특정 영역을 쉽게 식별할 수 있도록 하는 방시긍로 사용되고 있습니다. 이제, 에러나 경고가 "DrawLeftLeg" 루틴을 실행하는 중에 발생했다면, 여러분은 어떤 드로를 타게팅해야 할지 알 수 있을 겁니다.

레이블들은 커맨드 버퍼나 큐 기저상에 삽입될 수도 있습니다. 레이블 영역을 큐에서 시작하기 위해서는 다음과 같은 커맨드를 사용하게 됩니다:

이 커맨드는 다음 구조체를 받아들입니다:

이것은 "Creating ( and Desetroying ) a Debug Messenger" 에서 기술한 콜백에 반환되는 것과 같은 구조체입니다. color 는 레이어나 툴에서 레이블 이름을 위한 색상있는 텍스트를 생성하기 위해 사용될 수 있습니다. 만약 색상에 신경을 안 쓴다면, 툴이 색상을 사용하는 경우에는 이 파라미터의 각 값들을 "1.0" 으로 설정하십시오.

레이블링된 섹션을 종료하려면, 다음 함수를 호출합니다:

그것은 레이블을 취하지 않는다는 것에 주의하십시오. 이런 방식으로, end 는 "pop" 커맨드와 유사하게 작동합니다. 단지 특정 VkQueue 상에서 VkQueueBeginDebugUtilsLabelEXT 커맨드를 사용해 생성된 마지막 레이블을 종료시킵니다.

전체 영역을 정의하는 대신에, 단일 레이블을 특정 위치에 삽입할 수도 있습니다. 다음을 사용합니다:

만약 VkQueue 와 연관되는 레이블들을 정의했고 메시지가 발생했고 오브젝트 리스트에 특정 VkQueue 가 포함되어 있었다면, 콜백의 queueLabelCount 와 pQueueLables 데이터 필드가 적절한 칸텐츠와 함께 생성되어 있을 것입니다. 이 경우에, 그 데이터는 스택과 유사하게 저장될 것입니다. 그러므로 첫 번째 요소는 가장 최근의 레이블이며, 두 번째 요소는 가장 오래된 레이블입니다.

위에서 VkQueue 커맨드에 대해서 했던 것처럼 레이블을 커맨드를 사용해서 커맨드 버퍼에 삽입할 수 있습니다 :

얼마나 유사한지 확인해 보세요. 실제 차이는 VkQueue 대신에 VkCommandBuffer 를 요구한다는 것 뿐입니다. VkQueue 레이블처럼, 만약 pObjects 리스트에 VkCommandBuffer 오브젝트가 포함되어 있는 상태로 Debug Utils Messenger 콜백이 호출되었다면, 그리고 그 버퍼들이 레이블을 포함하고 있다면, 그 레이블들은 cmdBufLabelCount 와 pCmdBufLabels 필드에 추가될 것입니다. 또한, 큐 칸텐트와 마찬가지로, 데이터는 스택과 유사하게 반환되며, 첫 번째 레이블은 가장 최근이며 마지막 레이블은 가장 오래된 것입니다. 드로에 대한 예제를 살펴 보죠. 만약 버그가 DrawLeftLeg() 루틴에서 발생했다면, 에러가 반환될 때, cmdBufLableCount 와 pCmdBufLables 의 값들은 다음과 같은 식으로 보일 것입니다:

커맨드 버퍼 레이블의 특별한 특성( attribute )은 그것들이 커맨드 버퍼 경계를 넘어서서 활성화/비활성화 될 수 있다는 것입니다. 예를 들어, 프라이머리 커맨드 버퍼에서 레이블을 시작해서 세컨더리 커맨드 버퍼에서 레이블을 종료할 수 있습니다. 혹은 세컨더리 커맨드 버퍼에서 레이블을 시작해서 완전히 다른 세컨더리 커맨드 버퍼에서 레이블을 종료할 수 있습니다. 주의할 점이 있다면, 커맨드 버퍼 종속성 체인을 validation 메시지가 발생할 때 알 수 없다는 것입니다. Therefore, for those kind of messages you can only count on the contents of the one command buffer. However, for tools like RenderDoc, the spanning of command buffers should function correctly.

Application Usage Examples

Setting Up a Debug Utils Messenger and Callback

다음 코드 정보는 Debug Utils Messenger 콜백을 설정하고 그것을 사용하는 메신저를 생성하는 것을 보여 줍니다. 또한 이것이 익스텐션이기 때문에 vkGetInstanceProcAddr 를 사용해 VK_EXT_debug_utils 를 위한 벌칸 커맨드를 질의할 필요가 있음을 보여 줍니다 :

Using Object Names and Command Buffer Labels

다음 코드 정보는 레이블과 이름있는 오브젝트를 정의하는 방법을 보여 줍니다:

Updates to the Cube Demo

( 역주 : 그냥 VK_EXT_debug_report 에서 VK_EXT_debug_utils 로의 마이그레이션 샘플이므로 번역을 생략함 )

Future Validation Layer Improvements

이 튜토리얼을 발행하는 시점에, validation 레이어들은 VK_EXT_debug_report 익스텐션 콜백과 VK_EXT_debug_utils 익스텐션 콜백에 대해 거의 같은 정보를 반환할 것입니다. The extensions differ in that the VK_EXT_debug_report extension will also automatically add in VkCommandBuffer and VkQueue labels to the callback results and separate out some of the information so that the returned messages don’t seem as cluttered. 앞으로, 우리는 그런 에러 메시지들에 도움이 된다고 생각하는 부가적인 오브젝트 정보들을 추가할 계획입니다. validation 에러 메시지들이 부가적인 오브젝트 정보를 더 받아야 한다고 느낀다면, GitHub Issue 에 제출해 주십시오. 어떠한 메시지에 어떤 오브젝트 정보를 추가하기를 원하는지 명확하게 언급해 주세요. GitHub Pull Request 를 제공해 주실 수도 있습니다.

Conclusion

여러분도 보셨듯이, VK_EXT_debug_utils 익스텐션은 validation 레이어에 매우 많이 필요한 디버그 정보를 가지고 옵니다. 우리는 Vk_EXT_debug_utils 익스텐션을 Vulkan 1.1 을 이용할 수 있는 로더들에서부터 지원하기 시작했습니다. You don’t need to use Vulkan 1.1 to expose the extension functionality as the release of this extension and Vulkan 1.1 just happen to be timed together. 만약 이 익스텐션을 어떤 식으로든 사용하고자 한다면, 그냥 LunarG's Vulkan 1.1 SDK 를 시스템에 다운로드하시면 됩니다. VK_EXT_debug_utils 익스텐션을 찾아 봤으면 하는 바램입니다. 그것은 사용하기 편하고 유용하기 때문입니다.

Acknowlegements

이 아티클을 완료할 수 있도록 도움을 준 LunarG 의 Erika Johnson, Mark Lobodzinski, Mike Schuchardt 에게 감사드리고 싶습니다. 그리고 다시 한 번 검토해준 NVIDIA 의 Piers Daniel 에게도 감사드립니다.

주의 : 답이 틀릴 수도 있습니다. 그냥 정리하는 용도로 올립니다. 혹시라도 도움이 필요한 분이 있다면 도움이 되었으면 좋겠네요.

경고 : 숙제하려고 베끼는 데 사용하지 마십시오. 본인의 미래를 망칠 뿐입니다. 나중에 저를 원망하지 마세요.

부탁 : 문제 풀이가 잘못되었으면 지적해 주셨으면 좋겠습니다.



미래의 우주 정거장 속에 사는 사람들은 지구 중력을 받는 우리와 같은 환경 속에서 지낼 수 있다. 우주 정거장을 원 모양으로 만들어 일정한 빠르기로 회전시키면 된다. 우주 정거장의 반지름이 500 m 라고 할 때, 우주 정거장 안에 있는 사람과 정거장 바깥쪽 벽면 사이의 힘이 mg 크기가 되려면, 정거장은 1 분당 몇 번 회전해야 하는가?


결국 지구와 같은 중력을 느끼기 위한 정거장의 분당 회전수를 구하라는 것입니다.


[ 연습문제 5-5 ] 에 의해서 등속원운동하는 물체의 속도와 구심 가속도의 크기는 다음과 같습니다. r 은 반지름, ω 는 각속도, T 는 주기입니다.


식 1.


중력 가속도와 구심 가속도는 같은 개념입니다. 그러므로 그러므로 중력 가속도는 다음과 같습니다.


식 2.


1 회전에 T 분 걸리기 때문에, 1/T 는 분당 회전수가 됩니다.


식 3.


해답은 1.36 [번/분] 이기는 하지만 대충 값이 비슷하므로 정답으로 취급하겠습니다.

주의 : 초심자 튜토리얼은 아닙니다. 그러므로, 실제 API 호출 용례를 알고자 한다면, 샘플이나 튜토리얼을 찾아서 확인해 보세요.

주의 : 완전히 이해하고 작성한 글이 아니므로 잘못된 내용이 포함되어 있을 수 있습니다.

주의 : 이상하면 참고자료를 확인하세요.



Interface Block


일단 HLSL 의 경우에는 일반 구조체를 사용해서 각 셰이더 스테이지( Shader Stage )의 입력과 출력을 정의할 수 있도록 하고 있습니다. 버텍스( Vertex ) 셰이더의 예를 하나 살펴 보죠.



VertexInputVertexOutput 이라는 structGlobalBuffer 라는 cbuffer 가 정의되어 있습니다. 그리고 CommonVertexShader() 함수에서는 VertexInput 을 입력으로 받아 VertexOutput 을 산출합니다.


그리고 VertexInput VertexOutput 의 각 필드)에는 시맨틱( Semantic ) 이 지정되어 있습니다. 언어에서 신택스( Syntax )는 우리말로는 "문법" 으로 표현될 수 있으며, 언어의 문법이 옳은지 판단할 때 사용될 수 있습니다. 시맨틱은 "의미" 로 표현될 수 있으며, 말 그대로 의미상 옳은 지를 판단할 때 사용될 수 있습니다. 시맨틱을 사용하는 것의 장점이라면, 변수 이름이 아니라 시맨틱으로 그 변수의 의미를 특정할 수 있다는 것입니다.


OpenGL 이나 Vulkan 같은 경우에는 셰이더의 입력이나 출력을 인터페이스( Interface )라 정의하고 있습니다. 두 개의 스테이지를 각각 노드라 생각하고 데이터가 인터페이스를 통해서 왔다갔다 한다고 생각하면 무리가 없는 설정인 것 같습니다.


그런데 그 인터페이스에 매우 많은 데이터가 왔다갔다 하면 관리하기가 힘드니까 그것을 인터페이스 블록( Block )이라는 것으로 묶을 수 있도록 하고 있습니다[ 3 ][ 4 ]. 


인터페이스 블록의 구문은 구조체를 선언하는 것과 유사합니다.


storage_qualifier block_name

{

    <define members here>

} instance_name;


storage_qualifier 로는 uniform, in, out, buffer 등이 있습니다. 


  • uniform : global shader variable.

  • in : OpenGL 3.2 이상에서 지원되는 shader input.

  • out : OpenGL 3.2 이상에서 지원되는 shader output.

  • buffer : ARB_shader_storage_buffer_object 에 의해 지원되는 storage_buffer.


몇 개의 예를 [ 3 ] 에서 가져 와 보겠습니다.



Layout Qualifiers


그런데 storage_qualifier 들 중에서는 OpenGL 3.2 이상에서만 블록 형태로 지원되는 것들이 존재하기 때문에, 3.1 까지는 그냥 변수를 사용해서 입출력 데이터를 표현해야 했습니다. 이것 때문에 layout qualifier 라는 것이 필요했죠.


layout(qualifier1​, qualifier2​ = value, ...) variable_definition


여러 개의 변수들을 만들어 놓은 다음에 그것에 순서와 특성을 부여합니다. layout 으로 묶여 있는 괄호 안 쪽에 한정자( qualifier )들을 삽입합니다.


이 한정자의 종류는 다음과 같습니다. 물론 더 많은 한정자들이 있기는 하지만, Vulkan Spec 에서 언급한 한정자들만 나열했습니다.


  • location : 애트리뷰트( attribute ) 바인딩 순서를 지정합니다.

  • component : 애트리뷰트의 컴포넌트 개수를 지정합니다.


다음과 같은 식이죠. 



이렇게 되어 있으면 프로그램에서 position, texCoord, normal 이 들어 있는 구조체를 한 번에 glBindVertexArray() 로 지정했을 때 하나의 버텍스 내부에서 순차적으로 위치가 지정된 것처럼 동작하게 됩니다. location 이 하나 증가하면 float 4 개만큼의 메모리 offset 을 가진다고 보면 됩니다. HLSL 로 치자면 layout 은 레지스터 인덱스라고 생각해도 무방할 것 같습니다.


그러므로 다음과 같이 배열을 가지고 있는 경우에는 일반적으로는 float 4 배열 요소 개수나 구조체의 크기만큼 증가하게 됩니다.



그런데 가끔 float 4 크기보다는 작은 변수들을 하나의 레지스터로 묶고 싶을 때까 있습니다. HLSL 로 치자면 packoffset 과 유사한 개념이겠네요. 이 때 component 라는 한정자를 사용하게 됩니다. 이 컴포넌트 한정자를 지정하지 않으면 기본값은 0 이라고 합니다. 그런데 component qualifier 는 OpenGL 3.2 부터 ARB_explicit_attrib_location 을 통해서 버텍스 셰이더와 프래그먼트( fragment ) 셰이더에서만 지원하는 개념입니다.


아래의 몇 가지 예가 있습니다.



어쨌든 매우 불편한 개념인데요, HLSL 을 사용하면 딱히 신경쓰실 필요는 없습니다. 왜냐하면 HLSL 은 이미 인터페이스 블록같은 개념을 구조체를 통해 지원하고 있을 뿐더러 DXC 로 컴파일하게 되면 레이아웃을 자동으로 지정해 주기 때문입니다. 게다가 DXC 에 실행인자로 "-fspv-reflect" 를 지정하면 시맨틱으로 애트리뷰트를 획득하는 것도 가능합니다.


제일 위쪽에 있는 HLSL 코드 중에 VertexInput 을 리플렉션( reflection )하는 소스 코드를 한 번 살펴 보겠습니다.



그러면 다음과 같은 결과를 얻을 수 있습니다. 저같은 경우에는 사용하기 편하게 일부러 VkVertexInputAttributeDescription 맵의 형태로 만들었습니다. 소스코드를 보면 대부분의 내용은 이해하실 수 있을 것 같네요.


그림 1.


그림 1 의 디버깅 정보에는 "TANGENT0" 시맨틱에 대한 정보가 나와 있습니다.


DXC layout


이 HLSL 에서 이 레이아웃을 강제로 지정하는 방법도 있는데요, [ 4 ] 에서는 [[vk::location(x)]] 애트리뷰트를 사용하도록 하고 있습니다. 실제로 순서를 맘대로 바꿔 보도록 하겠습니다.



그런데 vk 애트리뷰트를 사용해서 레이아웃을 결정하신다면 DXC 의 실행 인자로 "-fvk-use-dx-layout" 를 지정하시는 것을 잊으시면 안 됩니다. 안 그러면 에러가 발생합니다.


어쨌든 DXC 를 실행하면 다음과 같이 "TANGENT0" 시맨틱의 location 이 5 번으로 변경되어 있는 것을 확인하실 수 있습니다.


그림 2.


그런데, 그림 2 를 자세히 보신 분들은 알아 차렸겠지만, offset 이 변하지 않았습니다. 이것은 변수 순서가 변경되지 않았기 때문에 발생하는 문제( ? )입니다.


그러므로 이런 경우에는 offset 을 구할 때 location 순서대로 정렬한 다음에 구하는 것이 좋습니다. 물론 offset 은 구조체 내의 메모리 위치이고 location 은 GPU 레지스터에서의 인덱스와 같은 것이기 때문에 굳이 offset 을 순서와 맞출 필요는 없습니다. 하지만 헷갈릴 우려가 있고 이게 성능에 어떤 영향을 미치는 지는 잘 모르겠습니다. 그러므로 순서를 맞추는 것이 좋을 것 같습니다.


결론


Spirv-Reflect 에 대해서 분석하다가 보니, 굳이 레이아웃에 대한 분석을 하기는 했지만, 일반적으로는 아무것도 하지 말고 그냥 순서대로 레이아웃이 결정되도록 놔두는 것이 좋다는 생각이 듭니다.


참고자료


[ 1 ] Vulkan 1.1.122 Specification. Khronos Group.


[ 2 ] Layout Qualifier (GLSL), OpenGL Wiki. https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL).


[ 3 ] Interface Block (GLSL). https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL).


[ 4 ] HLSL to SPIR-V Feature Mapping Manual. https://github.com/microsoft/DirectXShaderCompiler/blob/master/docs/SPIR-V.rst.

주의 : 답이 틀릴 수도 있습니다. 그냥 정리하는 용도로 올립니다. 혹시라도 도움이 필요한 분이 있다면 도움이 되었으면 좋겠네요.

주의 : 특별한 경우가 아니라면, 귀찮아서 문제는 안 옮깁니다.

경고 : 숙제하려고 베끼는 데 사용하지 마십시오. 본인의 미래를 망칠 뿐입니다. 나중에 저를 원망하지 마세요.

부탁 : 문제 풀이가 잘못되었으면 지적해 주셨으면 좋겠습니다.



문제에서는 "위성의 빠르기와 주기 사이에 T2 ∝ r3  관계가 있음을 보여라" 인데 문제가 약간 이상합니다. 아마도 주기와 반지름의 관계겠죠. 


일단 익히 알고 있는 식으로부터 시작하겠습니다. 위성의 가속도 a 는 다음과 같습니다. 여기에서 r 을 벡터로 표기하고 있는데요, 이건 지구 중심으로부터 위성까지의 벡터입니다.


식 1.



중력 F ( 중력가속도가 아니라 중력입니다 )는 다음과 같이 정의됩니다. G 는 중력상수, M 은 지구의 질량, m 은 위성의 질량입니다.


식 2.


이 경우에 위성의 가속도를 a 라했을 때 다음과 같은 관계가 성립합니다.


식 3.


식 1 에서 위성의 가속도를 알고 있기 때문에 식 3 에 대입하면 다음과 같습니다.


식 4.


식 4 를 정리하면 다음과 같습니다.


식 5.


식 5 를 통해 반지름의 세제곱은 주기의 제곱과 비례관계에 있음을 알 수 있습니다.


그런데 실제 케플러 3 법칙을 검색해 보니 비례식의 결론은 유사한데, 정확한 식이 다르게 나오는군요. 아마도 장축과 단축을 고려하지 않은 데서 차이가 발생하지 않나 싶네요...

+ Recent posts