Quick Reference
struct alignas(16) ObjectConstants {
DirectX::XMFLOAT4X4 worldViewProjection;
DirectX::XMFLOAT4 color;
};
static_assert(sizeof(ObjectConstants) % 16 == 0);Constant buffer ByteWidth는 16 bytes 배수여야 합니다. C++ 구조체 padding과 HLSL 16-byte register packing을 함께 맞춥니다.
생성과 Binding
D3D11_BUFFER_DESC desc{};
desc.ByteWidth = sizeof(ObjectConstants);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
ID3D11Buffer* cb = objectConstants.Get();
context->VSSetConstantBuffers(0, 1, &cb);HLSL의 register(b0)와 C++ binding slot 0을 맞춥니다. Vertex와 pixel shader는 각 stage에 별도로 bind합니다.
갱신 분리
Frame마다 한 번 바뀌는 camera·light와 object마다 바뀌는 transform을 같은 buffer에 넣으면 불필요한 복사가 늘 수 있습니다. Change frequency 기준으로 frame, material, object buffer를 나눕니다.
큰 ring buffer의 일부만 constant buffer로 연결하는 방식은 Direct3D 11.1의 *SetConstantBuffers1을 사용합니다. FirstConstant와 NumConstants는 16-byte constant 단위이고 지원 context를 ID3D11DeviceContext1로 얻어야 합니다. Direct3D 11.0만 지원해야 하면 buffer를 분리하거나 전체 buffer binding을 사용합니다.
Matrix를 업로드할 때 row-major·column-major 해석과 mul 순서를 함께 고정합니다. 무조건 transpose하는 관용구보다 C++와 HLSL contract를 한 방식으로 문서화합니다.
자주 틀리는 점
- Bool의 C++ 크기와 HLSL packing을 그대로 같다고 가정하지 않습니다. 32-bit 값을 사용합니다.
float3뒤 다음 scalar가 같은 16-byte register를 공유할 수 있는 packing을 확인합니다.- Buffer를 갱신했지만 다른 slot이나 stage에 bind하면 shader가 이전 값을 읽습니다.
- Object 수만큼 매번 resource를 만들지 않고 ring·pool 또는 subrange 전략을 검토합니다.
참고 링크
3 sources