• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

Direct3D11 공부 28일차(ComputeShader)

06 Jul 2021

Reading time ~2 minutes

ComputeShader

이 전에 말했던 GPU를 CPU 처럼 쓰는 방법을 이용하려면 Shader를 사용해야 한다.(지금까지 늘 GPU에 정보를 넘겨줄때 마다 Shader를 사용했으니 눈치 챌 만 하다.) 어? 그러면 지금까지 파이프라인에는 이 ComputeShader는 없었는데 언제 들어갈까?

IA - VS - (GS - CS - RS) - PS - OM

이 단계로 진행된다.

이번엔 10 * 8 * 3 = 240개의 스레드를 사용한다.

ComputeShader

//ByteAddressBuffer input; // SRV
RWByteAddressBuffer Output; // UAV

struct Group
{
    uint3 GroupID;
    uint3 GroupThreadID;
    uint3 DispatchThreadID;
    uint GroupIndex;
};

일단 Ouput만 받기 위해 Output만 받고 각각 받아온다.

struct ComputeInput
{
    uint3 GroupID : SV_GroupID;
    uint3 GroupThreadID : SV_GroupThreadID;
    uint3 DispatchThreadID : SV_DispatchThreadID;
    uint GroupIndex : SV_GroupIndex;
};

ComputeInput을 만들어 준다.

[numthreads(10, 8, 3)]
void CS(ComputeInput input)
{
    Group group;
    group.GroupID = asuint(input.GroupID);
    group.GroupThreadID = asuint(input.GroupThreadID);
    group.DispatchThreadID = asuint(input.DispatchThreadID);
    group.GroupIndex = asuint(input.GroupIndex);
    
    uint index = input.GroupIndex;
    
    // 4바이트인 uint 가 3개, 3개, 3개, 1개 그래서 10 * 4
    uint outAddress = index * 10 * 4;
    
    Output.Store3(outAddress + 0, asuint(group.GroupID)); // 12 바이트
    Output.Store3(outAddress + 12, asuint(group.GroupThreadID)); // 24
    Output.Store3(outAddress + 24, asuint(group.DispatchThreadID)); // 36
    Output.Store(outAddress + 36, asuint(group.GroupIndex)); // 36
}

각각 받아오는데 asuint를 활용해서 형 변환을 안전하게 한다.

그런 뒤, CPU로 전달할 때 메모리를 각각 크기만큼 띄어서 전달해 준다.

RawBufferDemo

void RawBufferDemo::Initialize()
{
	Shader* shader = new Shader(L"60_RawBuffer.fx");

	// 스레드 그룹 내에서 운영할 스레드 갯수
	UINT count = 10 * 8 * 3;

	struct Output
	{
		UINT GroupID[3];
		UINT GroupThreadID[3];
		UINT DispatchThreadID[3];
		UINT GroupIndex;
	};

	RawBuffer* rawBuffer = new RawBuffer(NULL, 0, sizeof(Output) * count);

	shader->AsUAV("Output")->SetUnorderedAccessView(rawBuffer->UAV());
	shader->Dispatch(0, 0, 1, 1, 1);

	Output* output = new Output[count];
	rawBuffer->CopyFromOutput(output);

	FILE* file;
	fopen_s(&file, "../Raw.csv", "w");

	for (UINT i = 0; i < count; i++)
	{
		Output temp = output[i];

		fprintf
		(
			file,
			"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
			i,
			temp.GroupID[0], temp.GroupID[1], temp.GroupID[2],
			temp.GroupThreadID[0], temp.GroupThreadID[1], temp.GroupThreadID[2],
			temp.DispatchThreadID[0], temp.DispatchThreadID[1], temp.DispatchThreadID[2],
			temp.GroupIndex
		);
	}
	fclose(file);
}

Output을 받아오고 이것들을 파일로 출력해준다.

0,0,0,0,0,0,0,0,0,0,0
1,0,0,0,1,0,0,1,0,0,1
2,0,0,0,2,0,0,2,0,0,2
3,0,0,0,3,0,0,3,0,0,3
4,0,0,0,4,0,0,4,0,0,4
5,0,0,0,5,0,0,5,0,0,5
6,0,0,0,6,0,0,6,0,0,6
7,0,0,0,7,0,0,7,0,0,7
8,0,0,0,8,0,0,8,0,0,8
9,0,0,0,9,0,0,9,0,0,9
10,0,0,0,0,1,0,0,1,0,10
11,0,0,0,1,1,0,1,1,0,11
12,0,0,0,2,1,0,2,1,0,12
13,0,0,0,3,1,0,3,1,0,13
14,0,0,0,4,1,0,4,1,0,14
15,0,0,0,5,1,0,5,1,0,15
16,0,0,0,6,1,0,6,1,0,16
17,0,0,0,7,1,0,7,1,0,17
18,0,0,0,8,1,0,8,1,0,18
.
.
.

각 ID 만큼 갖고오고 ID를 부여해서 출력한ㄷ.



DirectX Share Tweet +1