From d2c13bc4c10ebfd11d0f4e5bf6d2d95df4fdb1df Mon Sep 17 00:00:00 2001 From: vlj Date: Thu, 11 Jun 2015 20:42:38 +0200 Subject: [PATCH] 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. --- rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp | 67 +++++---------- rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp | 67 +-------------- rpcs3/Emu/RSX/D3D12/D3D12GSRender.h | 114 ++++++++++++++++++++++++-- rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp | 4 +- 4 files changed, 129 insertions(+), 123 deletions(-) diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index aee9dcb749..8dc28f8a86 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -192,7 +192,7 @@ std::vector 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 &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)); } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 1ab8d52163..944ac0c24f 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -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); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 2d950b1d67..d77f6e9def 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -43,22 +43,118 @@ typedef GSFrameBase2*(*GetGSFrameCb2)(); void SetGetD3DGSFrameCallback(GetGSFrameCb2 value); +template +struct InitHeap +{ + static T* Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags); +}; +template<> +struct InitHeap +{ + 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 +{ + 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 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 > 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::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 m_constantsData; // Vertex storage - DataHeap m_vertexIndexData; + DataHeap m_vertexIndexData; // Texture storage - DataHeap m_textureUploadData; - DataHeap m_textureData; + DataHeap m_textureUploadData; + DataHeap m_textureData; struct UAVHeap { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index 6e2383fb75..31e2fe8016 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -145,8 +145,8 @@ ID3D12Resource *uploadSingleTexture( const RSXTexture &texture, ID3D12Device *device, ID3D12GraphicsCommandList *commandList, - DataHeap &textureBuffersHeap, - DataHeap &textureHeap) + DataHeap &textureBuffersHeap, + DataHeap &textureHeap) { ID3D12Resource *vramTexture; size_t w = texture.GetWidth(), h = texture.GetHeight();