렌더링, 배치, 그래픽 카드, 성능 등에 대한 정보 + XNA?


12

제목이 약간 모호하다는 것을 알고 있지만 실제로 찾고있는 것을 설명하기는 어렵지만 여기에갑니다.

CPU 렌더링에 관해서는 성능을 추정하고 간단하게 할 수 있지만 기술 배경 정보가 부족하여 GPU에 관해서는 단서가 없습니다. XNA를 사용하고 있기 때문에 이론과 관련이 있다면 좋을 것입니다.

내가 실제로 알고 싶은 것은, 특정 그리기 작업을 수행 할 때 언제 그리고 어디서 (CPU / GPU) 어떻게됩니까? 배치 란 무엇입니까? 효과, 투영 등에는 어떤 영향이 있습니까? 데이터가 그래픽 카드에 유지됩니까 아니면 모든 단계에서 전송됩니까? 대역폭에 대해 이야기 할 때 그래픽 카드 내부 대역폭 또는 CPU에서 GPU 로의 파이프 라인에 대해 이야기하고 있습니까?
참고 : 실제로 드로잉 프로세스가 어떻게 진행되는지 에 대한 정보를 찾고 있지는 않습니다 .GPU의 비즈니스이기 때문에 그 이전의 모든 오버 헤드에 관심이 있습니다.

X 액션을 할 때 무슨 일이 일어나고 있는지 이해하고 싶습니다. 아키텍처와 관행을 그에 맞게 조정하고 싶습니다.

더 나은 게임을 작성하는 방법에 대한 더 많은 통찰력을 제공하는 기사 (코드 예제와 함께), 정보, 링크, 튜토리얼은 대단히 감사합니다. 감사 :)


2
이것이 원래 XNA 였지만 DirectX 태그를 추가했습니다. 기본 기술이므로 더 나은 답변을 얻는 데 도움이 될 수 있습니다. 또한 좋은 출발점을 줄 수있는 이 답변 을 확인하십시오 .
Andrew Russell

@AndrewRussell 감사합니다. :). 나는 실제로 그 기사를 포함하여 주제에 대한 다양한 기사를 읽었습니다. 그러나 내가 알고 싶은 모든 것을 다루지는 않았습니다.
Aidiakapi

답변:


20

나는 " 제한 "의 관점에서 성능을 생각하고 싶습니다 . 상당히 복잡하고 상호 연결된 시스템을 개념화하는 편리한 방법입니다. 성능 문제가 발생하면 "어떤 한계에 부딪 히고 있습니까?"라는 질문을합니다. (또는 : "CPU / GPU가 바인딩되어 있습니까?")

여러 수준으로 나눌 수 있습니다. 최상위 수준에는 CPU와 GPU가 있습니다. CPU 바운드 (GPU가 유휴 대기 중 CPU 대기) 또는 GPU 바운드 (CPU가 GPU 대기 중) 일 수 있습니다. 여기 주제에 대한 좋은 블로그 게시물이 있습니다.

더 세분화 할 수 있습니다. 온 CPU의 측면, 당신은 CPU의 캐시에 이미 데이터에 대한 모든 사이클을 사용하여 수 있습니다. 또는 메모리가 제한 되어 CPU가 유휴 상태가되어 주 메모리에서 데이터가 들어 오기를 기다리 므로 데이터 레이아웃을 최적화하십시오 . 당신은 그것을 아직도 더 나눌 수 있습니다.

내가 XNA에 대한 성능의 넓은 개요를하고있는 중이 야하지만 (내가 참조 형식 (의 할당 지적합니다 class하지 struct특히 X 박스 360에 - 일반적으로 저렴 사이클을 많이 구울 가비지 컬렉터를 게재 할 수있는 반면,) . 여기 참조 ) 자세한 내용은.

GPU의 측면, 나는 당신을 가리키는 의해 시작합니다 이 우수한 블로그 게시물 세부 정보를 많이 있습니다. 파이프 라인에 대한 미묘한 수준의 세부 정보 를 원하면 이 시리즈의 블로그 게시물을 읽으십시오 . ( 여기 더 간단한 것이 있습니다 ).

간단히 말해서, " 채우기 한도 "(백 버퍼에 쓸 수있는 픽셀 수-오버 버드 수), " 쉐이더 한도 "(쉐이더가 얼마나 복잡하고 " 텍스쳐 페치 / 텍스처 대역폭 제한 "(액세스 할 수있는 텍스처 데이터 양).

이제 우리는 CPU와 GPU가 상호 작용해야하는 곳 (다양한 API 및 드라이버를 통해)이 큰 문제에 직면했습니다. " 배치 한계 "및 " 대역폭 " 이 느슨하게 있습니다 . ( 앞서 언급 한 시리즈 중 하나 는 자세한 내용 을 다룹니다 .)

그러나 기본적으로 배치 ( 이미 알고 있듯이 )는 GraphicsDevice.Draw*함수 중 하나를 호출 할 때마다 (또는 XNA의 일부가 이를 수행 할 때마다) 발생합니다 SpriteBatch. 당신은 의심의 여지가 이미이 없다 읽으면서, 당신은 몇 천 개 얻을 수 * 프레임 당이의를. 이것은 CPU 한도이므로 다른 CPU 사용량과 경쟁합니다. 기본적으로 드라이버가 그리는 것에 대한 모든 것을 패키징하고 GPU로 전송하는 드라이버입니다.

그리고 GPU에 대한 대역폭 이 있습니다. 이것은 얼마나 많은 원시 데이터를 전송할 수 있는지입니다. 여기에는 렌더링 상태 및 셰이더 상수 / 매개 변수 설정 (월드 / 뷰 / 프로젝트 매트릭스와 같은 항목 포함)에서부터 DrawUser*함수 사용시 정점에 이르는 모든 배치와 함께 제공되는 모든 상태 정보가 포함 됩니다. 또한 어떤 통화를 포함 SetData하고 GetData등 텍스처, 버텍스 버퍼에를

이 시점에서 호출 할 수있는 모든 것 SetData(텍스처, 버텍스 및 인덱스 버퍼 등)뿐만 아니라 EffectGPU 메모리에도 남아 있다고 말해야합니다 . 지속적으로 GPU로 다시 전송되지는 않습니다. 해당 데이터를 참조하는 그리기 명령은 해당 데이터에 대한 포인터와 함께 전송됩니다.

(또한 : 메인 스레드에서만 드로우 명령을 보낼 수 있지만 SetData모든 스레드에서 할 수 있습니다 .)

XNA는 다소의 렌더링 상태 클래스 (물건을 복잡 BlendState, DepthStencilState등). 이 상태 데이터 드로우 콜마다 전송됩니다 (각 배치에서). 100 % 확신 할 수는 없지만 느리게 전송된다는 인상을 받고 있습니다 (변경되는 상태 만 전송 함). 어느 쪽이든, 상태 변화는 배치 비용에 비해 자유 지점까지 저렴합니다.

마지막으로 언급 할 것은 내부 GPU 파이프 라인 입니다. 여전히 읽어야하는 데이터에 쓰거나 여전히 써야하는 데이터를 읽음으로써 강제로 플러시하고 싶지 않습니다. 파이프 라인 플러시는 작업이 완료 될 때까지 대기하므로 데이터에 액세스 할 때 모든 것이 일관된 상태가됩니다.

주의해야 할 두 가지 특별한 경우는 다음과 같습니다. GetData동적으로 호출 -특히 RenderTarget2DGPU가 쓰고있는 것. 이것은 성능이 매우 나쁩니다.하지 마십시오.

다른 경우는 SetData정점 / 인덱스 버퍼를 호출 하는 것입니다. 이 작업을 자주 수행해야하는 경우 DynamicVertexBuffer(또한 DynamicIndexBuffer)를 사용하십시오. 이를 통해 GPU는 자주 변경 될 것을 알 수 있으며 파이프 라인 플러시를 피하기 위해 내부적으로 버퍼링 마법을 수행 할 수 있습니다.

또한 동적 버퍼는 DrawUser*메서드 보다 빠르지 만 필요한 최대 크기로 미리 할당해야합니다.

... 그리고 그것은 XNA 성능에 대해 내가 아는 모든 것입니다. :)


대단히 감사합니다! 입니다 정확히 내가보고 :) 바라고 있었는지.
Aidiakapi

1
백 개 프레임 당 배치 지나치게 비관적 인 소리. 내가 항상들은 규칙은 프레임 당 2K에서 3K 배치입니다. 일부 게임은 PC에서 최대 10K를 달성하는 것으로 알려져 있지만 달성하려면 상당한주의가 필요하다고 생각합니다.
Nathan Reed

맞습니다. "수백"수치는 "배치 배치 (batch batch) 배치"용지에서 발췌 한 것으로 "1GHz CPU의 100 %에서 25k 배치 / s"입니다. 그러나이 백서는 이제 10 년이 지난 지금부터 드라이버와 CPU가 크게 개선되었습니다. 나는 "몇 천"을 읽을 수 있도록 이것과 다른 것들을 업데이트 할 것이다.
Andrew Russell
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.