필요한 개념
- VertexBuffer : 정점 데이터의 정보를 저장
- IndexBuffer : 정점의 중복을 최소화하기 위해 그리는 번호를 지정
- Constant Buffer : 구조체를 변수로 묶어서 GPU로 보내기 위해 사용하는 버퍼
GPU 입장에서는 상수처럼 변수를 변경이 불가능(그래서 상수(Constant))
-> HLSL에서는 수정 불가지만, Effect에서는 값 수정이 가능하다.
-> 기존 HLSL에서는 VS, PS 접근 할 수 있는지도 지정했는데 Effect에서는 필요 없다.
간단하게 사용할때는 Shader->AsMatrix("World")->SetMatrix()
Shader에서 표현하면 전역변수 matrix world, float4, color등이 있다.
이것들이 다 cbuffer $Global영역에 들어간다.
- D3D11_USAGE : Cpu, Gpu 읽기, 쓰기 여부를 결정, 각 상태에 따라 렌더링 속도가 다름
* 속도 : IMMUTABLE > DEFAULT > DYNAMIC > STAGING
Flag/Attribute | CPU Read | CPU Write | GPU Read | GPU Write |
IMMUTABLE(읽기) | x | X | 0 | x |
DYNAMIC | x | 0 | 0 | x |
DEFAULT | 0 | x(*예외1) | 0 | 0 |
STAGING | 0 | 0 | 0 | 0 |
* 예외 1 : UpdateSubResource() 함수
<TIP>
- IndexBuffer -> IMMUTABLE 사용 (IndexBuffer는 한번 들어가면 절때 바뀌지 않아서)
- ConstantBuffer -> DYNAMIC 사용 (CPU에서 GPU로 계속 밀어 넣어주어야 해서)
.h
더보기
// 원래는 ID3D11Buffer(인터페이스)를 상속 받아 만든다.
//class VertexBuffer : public ID3D11Buffer
//{
//public:
// VertexBuffer();
// ~VertexBuffer();
//
//private:
//};
// 그러나 이렇게 맴버로 만들어도 됨(우리에게 좀 더 편함)
// Wrapper class란? 맴버를 감싸서 추가 기능을 제공하기 위한 클래스
class VertexBuffer
{
public:
VertexBuffer(void* data, UINT count, UINT stride, UINT slot = 0, bool bCpuWrite = false, bool bGpuWrite = false);
~VertexBuffer();
UINT Count() { return count; }
UINT Stride() { return stride; }
ID3D11Buffer* Buffer() { return buffer; }
void Render();
private:
ID3D11Buffer* buffer;
// 정점 정보를 들어올 데이터
void* data;
// 정점 개수
UINT count;
// 한 정점 크기
UINT stride;
UINT slot;
// Cpu 혹은 Gpu에서 쓸수 있는지
bool bCpuWrite;
bool bGpuWrite;
};
///////////////////////////////////////////////////////////////////////////////
class IndexBuffer
{
public:
IndexBuffer(void* data, UINT count);
~IndexBuffer();
UINT Count() { return count; }
ID3D11Buffer* Buffer() { return buffer; }
void Render();
private:
ID3D11Buffer* buffer;
void* data;
UINT count;
};
///////////////////////////////////////////////////////////////////////////////
class ConstantBuffer
{
public:
ConstantBuffer(void* data, UINT dataSize);
~ConstantBuffer();
ID3D11Buffer* Buffer() { return buffer; }
// 데이터를 밀어주기 위해 사용
void Render();
private:
ID3D11Buffer* buffer;
void* data;
// 전체 데이터 크기
UINT dataSize;
};
.Cpp
더보기
#include "Framework.h"
#include "Buffers.h"
VertexBuffer::VertexBuffer(void* data, UINT count, UINT stride, UINT slot, bool bCpuWrite, bool bGpuWrite)
: data(data), count(count), stride(stride), slot(slot)
, bCpuWrite(bCpuWrite), bGpuWrite(bGpuWrite)
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = stride * count;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
// Usage란? cpu 및 gpu의 읽기, 쓰기 상태를 알려줌, 각 상태에 따라 렌더링 속도가 다름
// 속도 IMMUTABLE > DEFAULT > DYNAMIC > STAGING
// IMMUTABLE
// - GPU 읽기만 가능(렌더링에서만 접근 가능)
// - 최초 생성시에 입력된 데이터를 수정할 수 없음
// - 가장 빠름
// ex) 모델같은 경우 읽어주고, 모델을 수정할 이유가 없다.
if (bCpuWrite == false && bGpuWrite == false)
desc.Usage = D3D11_USAGE_IMMUTABLE; // 상수느낌(불변)
// 어쩔 수 없이 정점을 바꿔야하는 경우(지형에서 brush로 지형을 바꾸는 경우라던가)
// Dynamic
// - CPU 쓰기(GPU로 보내는 것이 가능) -> Cpu에서 데이터를 써서 Gpu로 보낼수 있다는 얘기(데이터 수정 가능)
// - GPU 읽기(렌더링에서만 접근 가능) -> GPU 읽기만 가능하다는 의미는 렌더링용으로만 사용하겠단 의미
else if (bCpuWrite == true && bGpuWrite == false)
{
desc.Usage = D3D11_USAGE_DYNAMIC;
// Dynamic을 해도 CPUAccessFlags가 없다면 IMMUTABLE과 같은 취급됨
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
}
// Shader, GPU에서 뭔가를 처리했다면 Cpu로 데이터를 보내주기 위해 사용
// DEFAULT
// - CPU 읽기, GPU 읽기, 쓰기
// - 단, 예외적으로 UpdateSubResource()함수를 통해 CPU 쓰기가 가능
// UpdateSubResource()는 GPU로 복사하기 위한 락을 자기 스스로 걸고
// 복사를 하고 풀어버림, 그래서 시점 제어 불가, 상대적으로 느림, 거의쓰지 않음
else if (bCpuWrite == false && bGpuWrite == true)
{
desc.Usage = D3D11_USAGE_DEFAULT;
}
else
{
// STAGING
// - 모든 것이 가능한 상황(모든것 읽기, 쓰기 가능), 가장 느림
desc.Usage = D3D11_USAGE_STAGING;
// D3D11_CPU_ACCESS_READ : GPU에서 CPU로 보낼 수 있도록
// D3D11_CPU_ACCESS_WRITE : CPU에서 GPU로 보낼 수 있도록
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
}
// 밑에 것들은 GPU VRAM으로 복사해주기 위해 사용하는 부분
D3D11_SUBRESOURCE_DATA sub_resource = { 0 };
// 그릴 데이터의 시작 주소
sub_resource.pSysMem = data;
Check(D3D::GetDevice()->CreateBuffer(&desc, &sub_resource, &buffer));
}
VertexBuffer::~VertexBuffer()
{
SafeRelease(buffer);
}
void VertexBuffer::Render()
{
UINT offset = 0;
D3D::GetDC()->IASetVertexBuffers(slot, 1, &buffer, &stride, &offset);
}
///////////////////////////////////////////////////////////////////////////////
IndexBuffer::IndexBuffer(void* data, UINT count)
: data(data), count(count)
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = sizeof(UINT) * count;
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
// IndexBuffer는 한번 들어가면 절때 바뀌지 않는다.
desc.Usage = D3D11_USAGE_IMMUTABLE;
D3D11_SUBRESOURCE_DATA subResource = { 0 };
subResource.pSysMem = data;
Check(D3D::GetDevice()->CreateBuffer(&desc, &subResource, &buffer));
}
IndexBuffer::~IndexBuffer()
{
SafeRelease(buffer);
}
void IndexBuffer::Render()
{
D3D::GetDC()->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, 0);
}
///////////////////////////////////////////////////////////////////////////////
ConstantBuffer::ConstantBuffer(void* data, UINT dataSize) :
data(data), dataSize(dataSize)
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.ByteWidth = dataSize;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
// CPU에서 GPU로 계속 밀어 넣어주어야 함
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Check(D3D::GetDevice()->CreateBuffer(&desc, nullptr, &buffer));
}
ConstantBuffer::~ConstantBuffer()
{
SafeRelease(buffer);
}
void ConstantBuffer::Render()
{
// CPU->CPU로 데이터 밀어넣기 위해 MAP 사용
D3D11_MAPPED_SUBRESOURCE subResource;
// 쓰기용으로
// Map을 하면 GPU Buffer구역에 묶여 버림(다른 애들은 이 버퍼에 접근 불가->UnMap해줘야 함, 안그러면 터짐)
// Gpu에 있는 버퍼의 시작주소가 subResource를 통해 리턴됨(pData)
D3D::GetDC()->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
{
// D3D11_MAP을 Read로 주게 되면 반대로 Gpu데이터를 받을 수 있다. memcpy 순서를 바꿔야함
// 1. 받을 데이터 주소 2. 복사할 데이터 3. 크기
memcpy(subResource.pData, data, dataSize);
}
D3D::GetDC()->Unmap(buffer, 0);
}
'DirectX11 3D > 기본 문법' 카테고리의 다른 글
<DirectX11 3D> 34. ModelEditor - Converter(Assimp) (0) | 2022.02.07 |
---|---|
<DirectX11 3D> 32. Renderer (0) | 2022.02.07 |
<DirectX11 3D> 32. Renderer - PerFrame (0) | 2022.02.07 |
<DirectX11 3D> 32. Renderer - Transform (0) | 2022.02.07 |
<DirectX11 3D> 30. SkySphere (0) | 2022.01.29 |