✅ StructuredBuffer란?

StructuredBuffer는 GPU와의 연산을 위해 데이터를 구조체 단위로 주고받을 수 있게 해주는 DirectX11의 고급 데이터 버퍼입니다.

  • RawBuffer는 단순한 바이트 배열
  • StructuredBuffer는 명확한 구조체 배열

즉, 우리가 정해준 struct 타입의 데이터를 GPU로 넘기고, 계산된 결과를 다시 받아올 수 있게 해주는 구조입니다. 특히 인스턴싱에 필요한 행렬, 본 트랜스폼, 파티클 정보 등 구조화된 데이터를 반복적으로 다뤄야 할 때 유리합니다.


⚙️ StructuredBuffer 흐름 요약

  1. 입력 데이터 (Input)
  2. GPU에 데이터 전달 (CreateBuffer)
  3. Compute Shader에서 데이터 연산
  4. 결과 데이터 (Output)를 다시 CPU로 복사

📦 StructuredBuffer 클래스 구성

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 복사 (계산 결과 읽기)

🧪 Shader 코드 구성 (27. StructuredBufferDemo.fx)

1. 구조체 정의

struct InputDesc {
    matrix input;
};

struct OutputDesc {
    matrix result;
};

2. 버퍼 선언

StructuredBuffer<InputDesc> Input;
RWStructuredBuffer<OutputDesc> Output;

3. 연산 로직

[numthreads(500, 1, 1)]
void CS(uint id : SV_GroupIndex) {
    matrix result = Input[id].input * 2;
    Output[id].result = result;
}

4. Technique 설정

technique11 T0 {
    pass P0 {
        SetVertexShader(NULL);
        SetPixelShader(NULL);
        SetComputeShader(CompileShader(cs_5_0, CS()));
    }
}

🧪 StructuredBufferDemo.cpp에서 실제 사용

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를 곱하는 연산을 수행합니다.


🧠 왜 StructuredBuffer?

RawBuffer 방식StructuredBuffer 방식
단순 바이트 조작 (ByteAddressBuffer)구조체 기반 데이터 접근
가독성 낮음, 복잡한 offset 관리 필요명확한 타입 정의로 코드 명확
범용적이지만 위험성 있음안전하고 직관적인 구조

특히 행렬 정보, 본 트랜스폼, 파티클 등 “의미 있는 구조의 데이터”를 다룰 때 매우 적합합니다.


profile
李家네_공부방

0개의 댓글