StructuredBuffer는 GPU와의 연산을 위해 데이터를 구조체 단위로 주고받을 수 있게 해주는 DirectX11의 고급 데이터 버퍼입니다.
즉, 우리가 정해준 struct 타입의 데이터를 GPU로 넘기고, 계산된 결과를 다시 받아올 수 있게 해주는 구조입니다. 특히 인스턴싱에 필요한 행렬, 본 트랜스폼, 파티클 정보 등 구조화된 데이터를 반복적으로 다뤄야 할 때 유리합니다.
Input)CreateBuffer)Output)를 다시 CPU로 복사StructuredBuffer(
void* inputData, // 입력 데이터 포인터
uint32 inputStride, // 입력 구조체 크기
uint32 inputCount, // 입력 구조체 개수
uint32 outputStride = 0,
uint32 outputCount = 0
);
Output 관련 인자가 생략되면, Input 구조와 동일하게 맞춰서 자동 설정됩니다.
| 함수 | 설명 |
|---|---|
CreateInput() | 입력 버퍼 생성 (CPU에서 GPU로 전달) |
CreateSRV() | Shader Resource View (셰이더에서 읽기 전용으로 접근) |
CreateOutput() | 결과 버퍼 생성 (GPU 내부 연산 결과 저장용) |
CreateUAV() | Unordered Access View (셰이더에서 쓰기 가능) |
CreateResult() | 결과 복사용 CPU 접근 가능한 staging 버퍼 |
CopyToInput() | CPU → GPU 버퍼 복사 |
CopyFromOutput() | GPU → CPU 복사 (계산 결과 읽기) |
struct InputDesc {
matrix input;
};
struct OutputDesc {
matrix result;
};
StructuredBuffer<InputDesc> Input;
RWStructuredBuffer<OutputDesc> Output;
[numthreads(500, 1, 1)]
void CS(uint id : SV_GroupIndex) {
matrix result = Input[id].input * 2;
Output[id].result = result;
}
technique11 T0 {
pass P0 {
SetVertexShader(NULL);
SetPixelShader(NULL);
SetComputeShader(CompileShader(cs_5_0, CS()));
}
}
vector<Matrix> inputs(500, Matrix::Identity);
auto buffer = make_shared<StructuredBuffer>(
inputs.data(), sizeof(Matrix), 500, sizeof(Matrix), 500
);
_shader->GetSRV("Input")->SetResource(buffer->GetSRV().Get());
_shader->GetUAV("Output")->SetUnorderedAccessView(buffer->GetUAV().Get());
_shader->Dispatch(0, 0, 1, 1, 1);
vector<Matrix> outputs(500);
buffer->CopyFromOutput(outputs.data());
여기서 Dispatch(0, 0, 1, 1, 1)은 총 500개의 쓰레드를 x 방향으로 호출합니다. 그리고 각 쓰레드는 자신이 담당하는 행렬에 2를 곱하는 연산을 수행합니다.
| RawBuffer 방식 | StructuredBuffer 방식 |
|---|---|
| 단순 바이트 조작 (ByteAddressBuffer) | 구조체 기반 데이터 접근 |
| 가독성 낮음, 복잡한 offset 관리 필요 | 명확한 타입 정의로 코드 명확 |
| 범용적이지만 위험성 있음 | 안전하고 직관적인 구조 |
특히 행렬 정보, 본 트랜스폼, 파티클 등 “의미 있는 구조의 데이터”를 다룰 때 매우 적합합니다.