Skip to content

Instantly share code, notes, and snippets.

@benanil
Last active April 3, 2022 12:28
Show Gist options
  • Save benanil/c700bd6686ba14e7fdd1b3fcbea2dfd5 to your computer and use it in GitHub Desktop.
Save benanil/c700bd6686ba14e7fdd1b3fcbea2dfd5 to your computer and use it in GitHub Desktop.
#pragma once
#include "RenderingCommon.hpp"
#include "D3D12Backend.hpp"
#include <type_traits>
#include <exception>
namespace HSRendering
{
template<typename T>
class BufferBase
{
protected:
uint size;
ID3D12Resource* mpVidMemBuffer;
ID3D12Resource* mpSysMemBuffer;
virtual void Initialize(ID3D12Device2* device, T* data, uint _size,
ID3D12GraphicsCommandList* pCmd, D3D12_RESOURCE_STATES resourceState,
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE)
{
size = _size;
auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
auto resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(size * sizeof(T), flags);
ThrowIfFailed(device->CreateCommittedResource(
&heapProperties,
D3D12_HEAP_FLAG_NONE,
&resourceDesc,
resourceState,
nullptr, IID_PPV_ARGS(&mpVidMemBuffer)
));
auto sysHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);
ThrowIfFailed(device->CreateCommittedResource(
&sysHeapProperties,
D3D12_HEAP_FLAG_NONE,
&resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, IID_PPV_ARGS(&mpSysMemBuffer)
));
// copy to sys
void* mappedMem;
D3D12_RANGE range;
mpSysMemBuffer->Map(0, &range, &mappedMem);
memcpy(mappedMem, _data, sizeof(T) * size);
mpSysMemBuffer->Unmap(0, &range);
// upload to gpu
auto transion0 = CD3DX12_RESOURCE_BARRIER::Transition(mpVidMemBuffer,
resourceState,
D3D12_RESOURCE_STATE_COPY_DEST
);
pCmd->ResourceBarrier(1, &transion0);
pCmd->CopyBufferRegion(mpVidMemBuffer, 0, mpSysMemBuffer, 0, size * sizeof(T));
auto transion1 = CD3DX12_RESOURCE_BARRIER::Transition(mpVidMemBuffer,
D3D12_RESOURCE_STATE_COPY_DEST,
resourceState
);
pCmd->ResourceBarrier(1, &transion1);
}
};
template<typename T>
class VertexBuffer : public BufferBase<T>
{
public:
D3D12_VERTEX_BUFFER_VIEW view;
inline VertexBuffer(
ID3D12Device2* device, T* _data, uint _size, ID3D12GraphicsCommandList* pCmd, D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE)
{
Initialize(device, _data, _size, pCmd, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, flags);
mpVidMemBuffer->SetName(L"HS vertex buffer vid mem");
mpSysMemBuffer->SetName(L"HS vertex buffer sys mem");
view.BufferLocation = mpSysMemBuffer->GetGPUVirtualAddress();
view.SizeInBytes = sizeof(T) * _size;
view.StrideInBytes = sizeof(T);
}
~VertexBuffer() {
HSSafeRelease(mpVidMemBuffer);
HSSafeRelease(mpSysMemBuffer);
}
};
template<typename T>
class IndexBuffer : public BufferBase<T>
{
public:
D3D12_INDEX_BUFFER_VIEW view;
static inline constexpr DXGI_FORMAT TypeToFormat() {
// ensure UINT32 or UINT16 indices
static_assert(std::is_same<T, unsigned>() || std::is_same<T, unsigned short>());
if constexpr (std::is_same<T, uint>()) return DXGI_FORMAT_R32_UINT;
if constexpr (std::is_same<T, ushort>()) return DXGI_FORMAT_R16_UINT;
return DXGI_FORMAT_R32_UINT;
}
inline IndexBuffer(
ID3D12Device2* device, T* data, uint _size, ID3D12GraphicsCommandList* pCmd, D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE)
{
Inilialize(device, data, _size, pCmd, D3D12_RESOURCE_STATE_INDEX_BUFFER, flags);
mpVidMemBuffer->SetName(L"HS index buffer vid mem");
mpSysMemBuffer->SetName(L"HS index buffer sys mem");
view.BufferLocation = mpSysMemBuffer->GetGPUVirtualAddress();
view.SizeInBytes = sizeof(T) * _size;
view.Format = TypeToFormat();
}
~IndexBuffer() {
HSSafeRelease(mpVidMemBuffer);
HSSafeRelease(mpSysMemBuffer);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment