m_context->Dispatch(UINT(ceil(m_screenWidth / 256.0f)), m_screenHeight, 1);
CS는 PS와 다르게 어떤 픽셀을 그릴지 선택할 수 있다고 했었다. Dispatch의 인자를 보면 그룹을 나누고 있다.
screenwidth 가 1280일 경우 첫번째 인자는 5이므로 가로를 5개 그룹으로 나누고 세로는 m_screenHeight개 그룹으로 나눈다. 그리고 2차원 화면이므로 z는 그룹으로 나눌 필요 없으므로 1개이다.
RWTexture2D<float4> gOutput : register(u0);
이제 CS 쉐이더 코드를 보자. 먼저 맨 위에 RWTexture라고 써있는데 RW의 의미는 ReadWrite, 읽고 쓰기가 둘 다 가능한
Texture2D라는 의미다. 괄호안에 float4는 픽셀 포맷이다. register는 u로 시작하는데 UAV를 받아오기 때문이다.
[numthreads(256, 1, 1)] // TODO: 여러가지로 바꿔보기
void main(int3 gID : SV_GroupID, uint3 tID : SV_DispatchThreadID)
{
//TODO: groupID, DTid 등을 여러가지로 바꿔가면서 테스트
if (gID.x % uint(2) == 0)
{
gOutput[tID.xy] = float4(0.5, 0.5, 0.5, 1.0);
}
else
{
gOutput[tID.xy] = float4(1, 1, 1, 1) * scale;
}
}
진입점 함수 위에 [numthreads(256,1,1)]이 있다. numthreads는 하나의 그룹 안에서 실행될 수 있는 스레드의 개수다.
numthreads(X,Y,Z)에서 xyz를 곱한 값이 1024를 넘어가면 안되고 z가 64를 넘어가면 안된다. 지금은 스레드 그룹 하나당
스레드 256개다. Dispatch에서 정한 가로 그룹 개수가 5개이므로 가로의 총 스레드 개수는 1280 (screenWidth) 개다.
Dispatch 할때 가로 그룹 개수를 screenWidth를 256.0f 로 나누고 ceil 한 이유는 256으로 딱 나눠떨어진다는 보장이 없기
때문에 나눈 나머지에 대해서도 스레드 그룹을 추가할 수 있도록 올림을 하는 것이다.

Semantics SV_GroupThreadID는 그룹 내 스레드의 index를 의미하고 SV_GroupID는 group의 index다.
그림에서 왼쪽 위가 group들을 표현 한 것이고 오른쪽 아래가 그룹 내부 스레드들을 표현한 것이다.
각각 사각형 안에 있는 숫자 세개가 그룹 ID, 스레드 ID다. SV_DispatchTreadID는 그룹 내 스레드 ID가 아닌
전체 그룹에서 스레드 ID인데 어떤 계산식을 통해 구하는데 그냥 픽셀의 index라고 알아둬도 된다.
if (gID.x % uint(2) == 0)
{
gOutput[tID.xy] = float4(0.5, 0.5, 0.5, 1.0);
}
else
{
gOutput[tID.xy] = float4(1, 1, 1, 1) * scale;
}
gID가 groupID, tID가 threadID이므로 짝수번째 그룹에서 회색을 출력하고 홀수번째 그룹에서 흰색을 출력한다.
'그래픽스' 카테고리의 다른 글
| [그래픽스] Vertex Buffer을 생성할 때 Usage를 Dynamic으로 하면 터지는 이유 (0) | 2023.08.04 |
|---|---|
| [그래픽스] Compute Shader 개념 및 구조 (0) | 2023.07.24 |
| [그래픽스] 부드러운 그림자 - PCSS (0) | 2023.07.23 |
| [그래픽스] 부드러운 그림자 - PCF (0) | 2023.07.23 |
| [그래픽스] 그림자 (0) | 2023.07.23 |