Constant Buffer

์›๋ž˜๋ฒŒ๋ ˆยท2022๋…„ 8์›” 7์ผ
0

๐ŸŒž Constant Buffer(CBV)

  • Constant Buffer๋ž€? ( ์ƒ์ˆ˜ ๋ฒ„ํผ )

    Root Signature์˜ ํ•˜๋‚˜์˜ ์„œ๋ช…๋ฐฉ๋ฒ•์œผ๋กœ, ์•„๋ž˜์˜ ์˜ˆ์ œ๋Š” ์ƒ์ˆ˜๋ฅผ ๋‹ค๋ฃฐ ๋•Œ์˜ ๋ฒ„ํผ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.

    root constant๋กœ ๊ฐ’์€ ์ƒ์ˆ˜๋ฅผ ๋‹ค๋ฃฌ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
    Root Signatrue๋ฅผ ํ†ตํ•ด์„œ ๋ ˆ์ง€์Šคํ„ฐ ๊ณต๊ฐ„์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ๊ณผ ๊ทธ ๊ณต๊ฐ„์„ CmdList์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ๋ณ„๊ฐœ์˜ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

    /*---------------------------------------
    CmdList์— ConstantBuffer๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์†Œ๋“œ
    ----------------------------------------*/
    
    pCmdList->SetComputeRoot32BitConstant(0,seed); 
    // 0 is the parameter index, seed is used by the shaders
    
    /*------------------------------------------------------------
    Root Signature์˜ Init : Root Signature์— ๋‘๊ฐœ์˜ CBV๋ฅผ ์ถ”๊ฐ€ํ•œ ์ฝ”๋“œ
    -------------------------------------------------------------*/
    
    	CD3DX12_ROOT_PARAMETER param[2];
    		param[0].InitAsConstantBufferView(0); // 0๋ฒˆ - > b0 - > CBV
    		param[1].InitAsConstantBufferView(1); // 1๋ฒˆ - > b1 -> CBV
       
    		D3D12_ROOT_SIGNATURE_DESC sigDesc =CD3DX12_ROOT_SIGNATURE_DESC(2, param);
       
       
    /*-----------------------------------------------------------
    CommandQueue์˜ RenderBegin์— Root Signature์˜ ์„œ๋ช…์„ ํ•ด์ฃผ๋Š” ๋ฉ”์†Œ๋“œ
    -----------------------------------------------------------*/
    
    	_cmdList->SetGraphicsRootSignature(ROOT_SIGNATURE.Get());

๐ŸŒž Device์™€ CmdList ์ž‘์—…์˜ ์ฐจ์ด

  • Device์™€ CmdList์—์„œ์˜ ์ž‘์—…์— ์ฐจ์ด๋Š” ํ•ด๋‹น ์ผ์„ ์ฆ‰์‹œ ํ•˜๋Š”์ง€, ๋˜๋Š” ์ž‘์—…์„ ๋ชจ์•„์„œ ํ•œ๋ฒˆ์— ํ•˜๋Š”์ง€์— ์žˆ๋‹ค. CmdList์— ๊ฒฝ์šฐ ์ž‘์—…๋“ค์„ ๋ชจ์•„์„œ RenderEnd ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰ ๋  ๋•Œ ์‹คํ–‰ํ•˜๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.

๐ŸŒผ ์˜ˆ์‹œ Mesh.cpp

์œ„์˜ ์˜ˆ์‹œ๋ฅผ ์ž˜ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์ด Mesh.cpp ๋ถ€๋ถ„์ด๋‹ค.

void Mesh::Init(vector<Vertex>& vec)
{
	_vertexCount = static_cast<uint32>(vec.size());
	uint32 bufferSize = _vertexCount * sizeof(Vertex);

	D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
	D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);

	DEVICE->CreateCommittedResource(
		&heapProperty,
		D3D12_HEAP_FLAG_NONE,
		&desc,
		D3D12_RESOURCE_STATE_GENERIC_READ,
		nullptr,
		IID_PPV_ARGS(&_vertexBuffer));

	// Copy the triangle data to the vertex buffer.
	void* vertexDataBuffer = nullptr;
	CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
	_vertexBuffer->Map(0, &readRange, &vertexDataBuffer);
	::memcpy(vertexDataBuffer, &vec[0], bufferSize);
	_vertexBuffer->Unmap(0, nullptr);

	// Initialize the vertex buffer view.
	_vertexBufferView.BufferLocation = _vertexBuffer->GetGPUVirtualAddress();
	_vertexBufferView.StrideInBytes = sizeof(Vertex); // ์ •์  1๊ฐœ ํฌ๊ธฐ
	_vertexBufferView.SizeInBytes = bufferSize; // ๋ฒ„ํผ์˜ ํฌ๊ธฐ	
}

void Mesh::Render()
{
	CMD_LIST->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	CMD_LIST->IASetVertexBuffers(0, 1, &_vertexBufferView); // Slot: (0~15)
	CMD_LIST->DrawInstanced(_vertexCount, 1, 0, 0);
}

์œ„์˜ ์ฝ”๋“œ๊ฐ€ ํ•˜๋Š” ์ผ์„ ๋ง๋กœ ํ’€๋ฉด,
1) Init ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด์„œ CPU์—์„œ GPU์˜ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฒ„ํผ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
2) ์ƒ์„ฑ๋œ ๋ฒ„ํผ์—๋Š” ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์„ค๋ช…๋“ค์ด ์ž‘์„ฑ๋˜์–ด ์žˆ์„ ๊ฒƒ์ด๋‹ค.
3) ์ด๋ ‡๊ฒŒ ์ž‘์„ฑ๋œ ๋ฒ„ํผ์— ๋Œ€ํ•œ ์ฃผ์†Œ๋ฅผ GPU์˜ ๋ ˆ์ง€์Šคํ„ฐ์— ์ €์žฅ์„ ํ•ด์•ผํ•œ๋‹ค.
4) ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ Render ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด CmdList์— ์ถ”๊ฐ€๋ฅผ ํ•œ๋‹ค. ( ํ˜„์žฌ ์ž‘์—…์€ ์‹คํ–‰ X )
5) ๊ทธ ํ›„ CmdList์— ์ถ”๊ฐ€๋œ ์ž‘์—…๋“ค์ด ์‹คํ–‰๋  ๋•Œ, GPU์˜ ๋ฒ„ํผ์— ๋Œ€ํ•œ ๋˜๋Š” ์ฃผ์†Œ ๊ฐ’์„ ๋ ˆ์ง€์Šคํ„ฐ์— ์ €์žฅ์„ ํ•˜๊ฒŒ ๋˜๊ณ , Resource์˜ ๊ฐ’์„ ์ฐธ์กฐ ํ•  ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

์ฃผ์˜์‚ฌํ•ญ : ์ด๋ ‡๋“ฏ Device๋ฅผ ํ†ตํ•ด์„œ ์ž‘์—…์„ ํ•˜๋Š” ๊ฒƒ์€ ์ฆ‰์‹œ ์ผ์–ด๋‚˜๊ณ , CmdList๋ฅผ ์ด์šฉ์„ ํ•˜๋ฉด ํ›„์— ์ž‘์—…์ด ๋ฐœ์ƒํ•œ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ ์ฃผ์˜ํ•  ์ ์ด ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ Device๋ฅผ ํ†ตํ•ด์„œ ๊ฐ™์€ ๋ฒ„ํผ๋ฅผ ๋‘๋ฒˆ ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด, CmdList ์ž‘์—…์„ ํ•˜๊ฒŒ ๋  ๋•Œ ์ด๋ฅผ ๋ฐ˜์˜ํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค.

๐ŸŒผ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค.
๋‹จ์ˆœํžˆ GPU ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐฐ์—ด๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜์—ฌ ๊ฐ ์ธ๋ฑ์Šค์— ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

ConstantBuffer ํ—ค๋”

#pragma once
class ConstantBuffer
{
public:
	ConstantBuffer();
	~ConstantBuffer();

	void Init(uint32 size, uint32 count);

	void Clear();
	void PushData(int32 rootParamIndex, void* buffer, uint32 size);

	D3D12_GPU_VIRTUAL_ADDRESS GetGpuVirtualAddress(uint32 index);

private:
	void CreateBuffer();

private:
	ComPtr<ID3D12Resource>	_cbvBuffer;
	BYTE* _mappedBuffer = nullptr;
	uint32					_elementSize = 0;
	uint32					_elementCount = 0;
	
	uint32					_currentIndex = 0;

};

ConstantBuffer cpp

#include "pch.h"
#include "ConstantBuffer.h"
#include "Engine.h"

ConstantBuffer::ConstantBuffer()
{
}

ConstantBuffer::~ConstantBuffer()
{
	if (_cbvBuffer)
	{
		if (_cbvBuffer != nullptr)
			_cbvBuffer->Unmap(0, nullptr);

		_cbvBuffer = nullptr;
	}
}

void ConstantBuffer::Init(uint32 size, uint32 count)
{
	// ์ƒ์ˆ˜ ๋ฒ„ํผ๋Š” 256 ๋ฐ”์ดํŠธ ๋ฐฐ์ˆ˜๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค
	// 0 256 512 768
	_elementSize = (size + 255) & ~255;
	_elementCount = count;

	CreateBuffer();
}

void ConstantBuffer::CreateBuffer()
{
	uint32 bufferSize = _elementSize * _elementCount;
	D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
	D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(bufferSize);

	DEVICE->CreateCommittedResource(
		&heapProperty,
		D3D12_HEAP_FLAG_NONE,
		&desc,
		D3D12_RESOURCE_STATE_GENERIC_READ,
		nullptr,
		IID_PPV_ARGS(&_cbvBuffer));

	_cbvBuffer->Map(0, nullptr, reinterpret_cast<void**>(&_mappedBuffer));
}


void ConstantBuffer::Clear()
{
	_currentIndex = 0;
}

void ConstantBuffer::PushData(int32 rootParamIndex, void* buffer, uint32 size)
{
	assert(_currentIndex < _elementSize);
	
	::memcpy(&_mappedBuffer[_currentIndex * _elementSize], buffer, size);

	D3D12_GPU_VIRTUAL_ADDRESS address = GetGpuVirtualAddress(_currentIndex);
	CMD_LIST->SetGraphicsRootConstantBufferView(rootParamIndex, address);
	_currentIndex++;
}

D3D12_GPU_VIRTUAL_ADDRESS ConstantBuffer::GetGpuVirtualAddress(uint32 index)
{
	D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = _cbvBuffer->GetGPUVirtualAddress();
	objCBAddress += index * _elementSize;
	return objCBAddress;
}

์œ„์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ ConstantBuffer์— ๊ฐ’์„ ์—ฌ๋Ÿฌ๊ฐœ ์ €์žฅ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฐ์—ด์„ ๋งŒ๋“ค๊ฒŒ ๋œ๋‹ค.
์ด ๋ฐฐ์—ด์€ GPU ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ์œผ๋ฉด์„œ ํ˜„์žฌ์˜ index๊ฐ’์„ ์ถ”์ ํ•˜๋ฉด์„œ ํ•ด๋‹น ๊ฐ’์— buffer๊ฐ’์„ GPU์˜ ๋ ˆ์ง€์Šคํ„ฐ๋กœ ์˜ฎ๊ฒจ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

cf) Descriptor (DX11 -> view) :

ํฌ์ธํ„ฐ์ฒ˜๋Ÿผ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ๊ฒƒ

cf) Root Signature :

๋ ˆ์ง€์Šคํ„ฐ์— ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ฒ ๋‹ค ํ•˜๋Š” ๊ณ„์•ฝ์„œ์™€ ๊ฐ™์€ ๊ฒƒ

cf) Root Signature table์„ ์ด์šฉํ•˜๋Š” ์ด์œ  :

Root Signature๋Š” ๋ฌดํ•œ์ • ์‚ฌ์ด์ฆˆ๋ฅผ ๋Š˜๋ฆด ์ˆ˜ ์žˆ๋Š” ๊ทธ๋Ÿฌํ•œ ๊ณต๊ฐ„์ด ์•„๋‹ˆ๋‹ค. 
๋”ฐ๋ผ์„œ ์ด ๊ณต๊ฐ„์„ ๋” ๋„“ํ˜€์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ table์„ ์ด์šฉ ํ•  ๋ฟ ์•„๋‹ˆ๋ผ, 
์ด ๊ณต๊ฐ„์— ๋„ˆ๋ฌด ๋งŽ์€ ๋‚ด์šฉ์„ ์ž‘์„ฑ ํ•˜๊ฒŒ๋˜๋ฉด ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์— table์„ ์ด์šฉํ•œ๋‹ค.
profile
ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ๋‹ด์€ ๋ธ”๋กœ๊ทธ ์ž…๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€