9 분 소요

🔷 Constant Buffer

1. Root Signature의 파라미터에 상수 버퍼 생성

// (1) 상수버퍼 생성
CD3DX12_ROOT_PARAMETER param[2];
param[0].InitAsConstantBufferView(0); // b0 (CBV)
param[1].InitAsConstantBufferView(1); // b1
// (2) 파라미터 정보 설정
D3D12_ROOT_SIGNATURE_DESC desc = CD3DX12_ROOT_SIGNATURE_DESC(2, param);


2. ConstantBuffer Class

  • 상수 버퍼를 관리하는 클래스

상수 버퍼(constant buffer)

  • 셰이더 프로그램에서 참조하는 상수 자료를 담는 GPU자원
  • CPU가 프레임 마다 한 번씩 갱신하는 것이 일반적
  • 버퍼의 크기는 최소하드웨어 할당 크기(256byte)의 배수

ComPtr<ID3D12Resource>	_cbvBuffer; // 상수 버퍼
BYTE*					_mappedBuffer = nullptr;
uint32					_elementSize = 0;
uint32					_elementCount = 0;

uint32					_currentIndex = 0;

1) 상수버퍼 크기 및 개수 설정

_elementSize = (size + 255) & ~255;	// 크기 (256byte의 배수)
_elementCount = count;				// 버퍼 개수

2) 상수버퍼 생성

uint32 bufferSize = _elementSize * _elementCount;
D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); // 업로드 힙
D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);

// 상수버퍼 생성
MyEngine->GetDevice()->GetDevice()->CreateCommittedResource(
	&heapProperty,
	D3D12_HEAP_FLAG_NONE,
	&desc,
	D3D12_RESOURCE_STATE_GENERIC_READ,
	nullptr,
	IID_PPV_ARGS(&_cbvBuffer));

3) 상수버퍼 값 설정

// (1) 자료를 올리기 위한 상수버퍼를 가리키는 포인터 얻기
_cbvBuffer->Map(0, nullptr, reinterpret_cast<void**>(&_mappedBuffer));
assert(_currentIndex < _elementSize);
// (2) CPU(시스템메모리)에서 자료를 상수버퍼에 복사
::memcpy(&_mappedBuffer[_currentIndex * _elementSize], buffer, size);

4) 파이프라인에 상수버퍼 바인딩

D3D12_GPU_VIRTUAL_ADDRESS address = GetGpuVirtualAddress(_currentIndex);
MyEngine->GetCommandQueue()->GetCommandList()->SetGraphicsRootConstantBufferView(rootParamIndex, address);
_currentIndex++;

상수버퍼 포인터 얻기

	D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = _cbvBuffer->GetGPUVirtualAddress(); // GPU상의 시작주소를 알려준다
	objCBAddress += index * _elementSize;
	return objCBAddress;

Mesh에서 값 설정

MyEngine->GetConstantBuffer()->PushData(0, &_transform, sizeof(_transform)); // 좌표 (b0)
MyEngine->GetConstantBuffer()->PushData(1, &_transform, sizeof(_transform)); // 색 (b1)


3. HLSL에 상수버퍼 자료 추가

1) 상수버퍼

  • register b를 사용한다
cbuffer TEST_b0 : register(b0)
{
    float4 offset0;
}

cbuffer TEST_b1 : register(b1)
{
    float4 offset1;
}
VS_OUT VS_Main(VS_IN input)
{
    VS_OUT output = (VS_OUT)0;

    output.pos = float4(input.pos, 1.f);
    output.pos += offset0; // pos에 상수버퍼 값 더하기
    output.color = input.color;
    output.color += offset1; // color에 상수버퍼 값 더하기

    return output;
}


📑. 참고

카테고리:

업데이트:

댓글남기기