d3d12: Use a commited resource for constant buffer

Since we rarely use more than 1k of constant data we waste space due to
alignment requirement with heap so use a commited resource instead.
This commit is contained in:
vlj 2015-06-11 20:42:38 +02:00 committed by Vincent Lejeune
parent 2f54482592
commit d2c13bc4c1
4 changed files with 129 additions and 123 deletions

View File

@ -192,7 +192,7 @@ std::vector<VertexBufferFormat> FormatVertexData(const RSXVertexData *m_vertex_d
* Create a new vertex buffer with attributes from vbf using vertexIndexHeap as storage heap.
*/
static
ID3D12Resource *createVertexBuffer(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, ID3D12Device *device, DataHeap &vertexIndexHeap)
ID3D12Resource *createVertexBuffer(const VertexBufferFormat &vbf, const RSXVertexData *vertexData, ID3D12Device *device, DataHeap<ID3D12Heap, 65536> &vertexIndexHeap)
{
size_t subBufferSize = vbf.range.second - vbf.range.first + 1;
// Make multiple of stride
@ -423,31 +423,23 @@ void D3D12GSRender::setScaleOffset()
// Scale offset buffer
// Separate constant buffer
ID3D12Resource *scaleOffsetBuffer;
check(m_device->CreatePlacedResource(
m_constantsData.m_heap,
heapOffset,
&getBufferResourceDesc(256),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&scaleOffsetBuffer)
));
D3D12_RANGE range = { heapOffset, heapOffset + 256 };
void *scaleOffsetMap;
check(scaleOffsetBuffer->Map(0, nullptr, &scaleOffsetMap));
streamToBuffer(scaleOffsetMap, scaleOffsetMat, 16 * sizeof(float));
check(m_constantsData.m_heap->Map(0, &range, &scaleOffsetMap));
streamToBuffer((char*)scaleOffsetMap + heapOffset, scaleOffsetMat, 16 * sizeof(float));
int isAlphaTested = m_set_alpha_test;
streamToBuffer((char*)scaleOffsetMap + 16 * sizeof(float), &isAlphaTested, sizeof(int));
streamToBuffer((char*)scaleOffsetMap + 17 * sizeof(float), &m_alpha_ref, sizeof(float));
scaleOffsetBuffer->Unmap(0, nullptr);
streamToBuffer((char*)scaleOffsetMap + heapOffset + 16 * sizeof(float), &isAlphaTested, sizeof(int));
streamToBuffer((char*)scaleOffsetMap + heapOffset + 17 * sizeof(float), &m_alpha_ref, sizeof(float));
m_constantsData.m_heap->Unmap(0, &range);
D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDesc = {};
constantBufferViewDesc.BufferLocation = scaleOffsetBuffer->GetGPUVirtualAddress();
constantBufferViewDesc.BufferLocation = m_constantsData.m_heap->GetGPUVirtualAddress() + heapOffset;
constantBufferViewDesc.SizeInBytes = (UINT)256;
D3D12_CPU_DESCRIPTOR_HANDLE Handle = getCurrentResourceStorage().m_scaleOffsetDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
Handle.ptr += getCurrentResourceStorage().m_currentScaleOffsetBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle);
m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, 256, scaleOffsetBuffer));
// m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, 256, scaleOffsetBuffer));
}
void D3D12GSRender::FillVertexShaderConstantsBuffer()
@ -464,28 +456,20 @@ void D3D12GSRender::FillVertexShaderConstantsBuffer()
assert(m_constantsData.canAlloc(bufferSize));
size_t heapOffset = m_constantsData.alloc(bufferSize);
ID3D12Resource *constantsBuffer;
check(m_device->CreatePlacedResource(
m_constantsData.m_heap,
heapOffset,
&getBufferResourceDesc(bufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&constantsBuffer)
));
D3D12_RANGE range = { heapOffset, heapOffset + bufferSize };
void *constantsBufferMap;
check(constantsBuffer->Map(0, nullptr, &constantsBufferMap));
streamBuffer(constantsBufferMap, vertexConstantShadowCopy, bufferSize);
constantsBuffer->Unmap(0, nullptr);
check(m_constantsData.m_heap->Map(0, &range, &constantsBufferMap));
streamBuffer((char*)constantsBufferMap + heapOffset, vertexConstantShadowCopy, bufferSize);
m_constantsData.m_heap->Unmap(0, &range);
D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDesc = {};
constantBufferViewDesc.BufferLocation = constantsBuffer->GetGPUVirtualAddress();
constantBufferViewDesc.BufferLocation = m_constantsData.m_heap->GetGPUVirtualAddress() + heapOffset;
constantBufferViewDesc.SizeInBytes = (UINT)bufferSize;
D3D12_CPU_DESCRIPTOR_HANDLE Handle = getCurrentResourceStorage().m_constantsBufferDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
Handle.ptr += getCurrentResourceStorage().m_constantsBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle);
m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, bufferSize, constantsBuffer));
// m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, bufferSize, constantsBuffer));
}
void D3D12GSRender::FillPixelShaderConstantsBuffer()
@ -499,19 +483,11 @@ void D3D12GSRender::FillPixelShaderConstantsBuffer()
assert(m_constantsData.canAlloc(bufferSize));
size_t heapOffset = m_constantsData.alloc(bufferSize);
ID3D12Resource *constantsBuffer;
check(m_device->CreatePlacedResource(
m_constantsData.m_heap,
heapOffset,
&getBufferResourceDesc(bufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&constantsBuffer)
));
D3D12_RANGE range = { heapOffset, heapOffset + bufferSize };
size_t offset = 0;
void *constantsBufferMap;
check(constantsBuffer->Map(0, nullptr, &constantsBufferMap));
check(m_constantsData.m_heap->Map(0, &range, &constantsBufferMap));
for (size_t offsetInFP : fragmentOffset)
{
u32 vector[4];
@ -546,19 +522,18 @@ void D3D12GSRender::FillPixelShaderConstantsBuffer()
vector[3] = c3;
}
streamToBuffer((char*)constantsBufferMap + offset, vector, 4 * sizeof(u32));
streamToBuffer((char*)constantsBufferMap + heapOffset + offset, vector, 4 * sizeof(u32));
offset += 4 * sizeof(u32);
}
constantsBuffer->Unmap(0, nullptr);
m_constantsData.m_heap->Unmap(0, &range);
D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDesc = {};
constantBufferViewDesc.BufferLocation = constantsBuffer->GetGPUVirtualAddress();
constantBufferViewDesc.BufferLocation = m_constantsData.m_heap->GetGPUVirtualAddress() + heapOffset;
constantBufferViewDesc.SizeInBytes = (UINT)bufferSize;
D3D12_CPU_DESCRIPTOR_HANDLE Handle = getCurrentResourceStorage().m_constantsBufferDescriptorsHeap->GetCPUDescriptorHandleForHeapStart();
Handle.ptr += getCurrentResourceStorage().m_constantsBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle);
m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, bufferSize, constantsBuffer));
// m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, bufferSize, constantsBuffer));
}

View File

@ -14,71 +14,6 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value)
GetGSFrame = value;
}
void DataHeap::Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags)
{
m_size = heapSize;
D3D12_HEAP_DESC heapDesc = {};
heapDesc.SizeInBytes = m_size;
heapDesc.Properties.Type = type;
heapDesc.Flags = flags;
check(device->CreateHeap(&heapDesc, IID_PPV_ARGS(&m_heap)));
m_putPos = 0;
m_getPos = m_size - 1;
}
bool DataHeap::canAlloc(size_t size)
{
size_t putPos = m_putPos, getPos = m_getPos;
size_t allocSize = powerOf2Align(size, 65536);
if (putPos + allocSize < m_size)
{
// range before get
if (putPos + allocSize < getPos)
return true;
// range after get
if (putPos > getPos)
return true;
return false;
}
else
{
// ..]....[..get..
if (putPos < getPos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (allocSize > getPos)
return false;
return true;
}
}
size_t DataHeap::alloc(size_t size)
{
assert(canAlloc(size));
size_t putPos = m_putPos;
if (putPos + size < m_size)
{
m_putPos += powerOf2Align(size, 65536);
return putPos;
}
else
{
m_putPos = powerOf2Align(size, 65536);
return 0;
}
}
void DataHeap::Release()
{
m_heap->Release();
for (auto tmp : m_resourceStoredSinceLastSync)
{
std::get<2>(tmp)->Release();
}
}
GarbageCollectionThread::GarbageCollectionThread()
{
m_worker = std::thread([this]() {
@ -441,7 +376,7 @@ D3D12GSRender::D3D12GSRender()
m_rtts.Init(m_device);
m_constantsData.Init(m_device, 1024 * 1024 * 128, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS);
m_constantsData.Init(m_device, 1024 * 1024 * 128, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_NONE);
m_vertexIndexData.Init(m_device, 1024 * 1024 * 128, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS);
m_textureUploadData.Init(m_device, 1024 * 1024 * 256, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS);
m_textureData.Init(m_device, 1024 * 1024 * 512, D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES);

View File

@ -43,22 +43,118 @@ typedef GSFrameBase2*(*GetGSFrameCb2)();
void SetGetD3DGSFrameCallback(GetGSFrameCb2 value);
template<typename T>
struct InitHeap
{
static T* Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags);
};
template<>
struct InitHeap<ID3D12Heap>
{
static ID3D12Heap* Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags)
{
ID3D12Heap *result;
D3D12_HEAP_DESC heapDesc = {};
heapDesc.SizeInBytes = heapSize;
heapDesc.Properties.Type = type;
heapDesc.Flags = flags;
check(device->CreateHeap(&heapDesc, IID_PPV_ARGS(&result)));
return result;
}
};
template<>
struct InitHeap<ID3D12Resource>
{
static ID3D12Resource* Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags)
{
ID3D12Resource *result;
D3D12_HEAP_PROPERTIES heapProperties = {};
heapProperties.Type = type;
check(device->CreateCommittedResource(&heapProperties,
flags,
&getBufferResourceDesc(heapSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&result))
);
return result;
}
};
template<typename T, size_t Alignment>
struct DataHeap
{
ID3D12Heap *m_heap;
T *m_heap;
size_t m_size;
size_t m_putPos, // Start of free space
m_getPos; // End of free space
std::vector<std::tuple<size_t, size_t, ID3D12Resource *> > m_resourceStoredSinceLastSync;
void Init(ID3D12Device *, size_t, D3D12_HEAP_TYPE, D3D12_HEAP_FLAGS);
void Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags)
{
m_size = heapSize;
m_heap = InitHeap<T>::Init(device, heapSize, type, flags);
m_putPos = 0;
m_getPos = m_size - 1;
}
/**
* Does alloc cross get position ?
*/
bool canAlloc(size_t size);
size_t alloc(size_t size);
void Release();
bool canAlloc(size_t size)
{
size_t putPos = m_putPos, getPos = m_getPos;
size_t allocSize = powerOf2Align(size, Alignment);
if (putPos + allocSize < m_size)
{
// range before get
if (putPos + allocSize < getPos)
return true;
// range after get
if (putPos > getPos)
return true;
return false;
}
else
{
// ..]....[..get..
if (putPos < getPos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (allocSize > getPos)
return false;
return true;
}
}
size_t alloc(size_t size)
{
assert(canAlloc(size));
size_t putPos = m_putPos;
if (putPos + size < m_size)
{
m_putPos += powerOf2Align(size, Alignment);
return putPos;
}
else
{
m_putPos = powerOf2Align(size, Alignment);
return 0;
}
}
void Release()
{
m_heap->Release();
for (auto tmp : m_resourceStoredSinceLastSync)
{
std::get<2>(tmp)->Release();
}
}
};
struct GarbageCollectionThread
@ -129,12 +225,12 @@ private:
ResourceStorage &getNonCurrentResourceStorage();
// Constants storage
DataHeap m_constantsData;
DataHeap<ID3D12Resource, 256> m_constantsData;
// Vertex storage
DataHeap m_vertexIndexData;
DataHeap<ID3D12Heap, 65536> m_vertexIndexData;
// Texture storage
DataHeap m_textureUploadData;
DataHeap m_textureData;
DataHeap<ID3D12Heap, 65536> m_textureUploadData;
DataHeap<ID3D12Heap, 65536> m_textureData;
struct UAVHeap
{

View File

@ -145,8 +145,8 @@ ID3D12Resource *uploadSingleTexture(
const RSXTexture &texture,
ID3D12Device *device,
ID3D12GraphicsCommandList *commandList,
DataHeap &textureBuffersHeap,
DataHeap &textureHeap)
DataHeap<ID3D12Heap, 65536> &textureBuffersHeap,
DataHeap<ID3D12Heap, 65536> &textureHeap)
{
ID3D12Resource *vramTexture;
size_t w = texture.GetWidth(), h = texture.GetHeight();