Root Signature는 셰이더가 사용할 리소스들의 '기안서'라고 볼 수 있습니다. 즉, GPU 내에서 어떤 리소스를 사용할 것인지 명시하는 구조입니다.
D3D12_ROOT_SIGNATURE_DESC sigDesc = CD3DX12_ROOT_SIGNATURE_DESC(D3D12_DEFAULT);
sigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT 플래그는 정점 레이아웃 정보를 사용하도록 허용합니다.D3D12SerializeRootSignature로 직렬화하고, CreateRootSignature로 생성합니다.Root Signature는 기능이 확장될수록 더 많은 파라미터가 필요하므로, 기초 렌더링에서는 간단한 형태로 시작합니다.
Mesh는 정점 데이터(Vertex)를 관리하며, GPU에 업로드할 VertexBuffer를 생성합니다.
D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);
UPLOAD 메모리: CPU가 접근 가능하며 실시간 변경에 적합 (ex. UI, 움직이는 객체)DEFAULT 메모리: GPU 전용, 읽기 전용 데이터 (ex. 나무, 돌처럼 고정된 오브젝트)버퍼에 데이터를 복사하는 과정은 다음과 같습니다:
_vertexBuffer->Map(0, &readRange, &vertexDataBuffer);
::memcpy(vertexDataBuffer, &vec[0], bufferSize);
_vertexBuffer->Unmap(0, nullptr);
CMD_LIST->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
CMD_LIST->IASetVertexBuffers(0, 1, &_vertexBufferView);
CMD_LIST->DrawInstanced(_vertexCount, 1, 0, 0);
TriangleList: 3개의 정점을 하나의 삼각형으로 인식셰이더는 HLSL(HIGH LEVEL SHADER LANGUAGE)로 작성합니다. 보통 .hlsl 또는 .hlsli 확장자로 저장합니다.
struct VS_IN {
float3 pos : POSITION;
float4 color : COLOR;
};
struct VS_OUT {
float4 pos : SV_Position;
float4 color : COLOR;
};
VS_OUT VS_Main(VS_IN input) {
VS_OUT output;
output.pos = float4(input.pos, 1.f);
output.color = input.color;
return output;
}
float4 PS_Main(VS_OUT input) : SV_Target {
return input.color;
}
이 셰이더를 컴파일하여 GPU가 사용할 수 있도록 합니다.
D3DCompileFromFile(path.c_str(), nullptr, ..., "VS_Main", "vs_5_0", ..., &blob, ...);
컴파일 후 얻은 Blob은 PSO 설정 시 셰이더 코드로 삽입됩니다.
정점 데이터의 레이아웃을 설명해주는 구조입니다. 이는 Vertex Shader의 입력과 정확히 일치해야 합니다.
D3D12_INPUT_ELEMENT_DESC layout[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, ..., 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, ..., 12 },
};
임시로 삼각형 하나를 생성해 화면 출력 테스트를 합니다.
vector<Vertex> vec(3);
vec[0].pos = Vec3(0.f, 0.5f, 0.5f); vec[0].color = Vec4(1.f, 0.f, 0.f, 1.f);
vec[1].pos = Vec3(0.5f, -0.5f, 0.5f); vec[1].color = Vec4(0.f, 1.0f, 0.f, 1.f);
vec[2].pos = Vec3(-0.5f, -0.5f, 0.5f); vec[2].color = Vec4(0.f, 0.f, 1.f, 1.f);
정점은 위치(Pos)와 색상(Color) 정보를 갖고 있으며, 화면 중심이 (0,0)입니다.
CMD_LIST->DrawInstanced(3, 1, 0, 0);
DrawIndexed, DrawInstanced 등을 사용할 수 있습니다.| 순서 | 단계 | 설명 |
|---|---|---|
| 1 | Device & SwapChain 생성 | 장치 초기화 |
| 2 | VertexBuffer 생성 | 정점 데이터 업로드 |
| 3 | RootSignature 설정 | 셰이더 자원 정의 |
| 4 | Shader 컴파일 및 PSO 설정 | 렌더링 파이프라인 구성 |
| 5 | Viewport/Scissor 설정 | 화면 설정 |
| 6 | CommandList에 렌더 명령 입력 | GPU에 명령 전달 |
| 7 | Present | 출력 버퍼 교체 |
이 단계들을 이해했다면, 렌더링 파이프라인을 도식으로 그려보며 흐름을 시각화하는 것도 추천합니다.
(예: Input Assembler → Vertex Shader → Rasterizer → Pixel Shader → Output Merger)