diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 05ef59f54d..c8919dafb3 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -394,16 +394,15 @@ void D3D12GSRender::setScaleOffset() scaleOffsetMat[3] /= RSXThread::m_width / RSXThread::m_width_scale; scaleOffsetMat[7] /= RSXThread::m_height / RSXThread::m_height_scale; - size_t constantBuffersHeapOffset = m_perFrameStorage.m_constantsBuffersHeapFreeSpace; - // 65536 alignment - constantBuffersHeapOffset = (constantBuffersHeapOffset + 65536 - 1) & ~65535; + assert(m_constantsData.canAlloc(256)); + size_t heapOffset = m_constantsData.alloc(256); // Scale offset buffer // Separate constant buffer ID3D12Resource *scaleOffsetBuffer; check(m_device->CreatePlacedResource( - m_perFrameStorage.m_constantsBuffersHeap, - constantBuffersHeapOffset, + m_constantsData.m_heap, + heapOffset, &getBufferResourceDesc(256), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, @@ -421,8 +420,7 @@ void D3D12GSRender::setScaleOffset() D3D12_CPU_DESCRIPTOR_HANDLE Handle = m_perFrameStorage.m_scaleOffsetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); Handle.ptr += m_perFrameStorage.m_currentScaleOffsetBufferIndex * m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); m_device->CreateConstantBufferView(&constantBufferViewDesc, Handle); - m_perFrameStorage.m_constantsBuffersHeapFreeSpace = constantBuffersHeapOffset + 256; - m_perFrameStorage.m_inflightResources.push_back(scaleOffsetBuffer); + m_constantsData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, 256, scaleOffsetBuffer)); } void D3D12GSRender::FillVertexShaderConstantsBuffer() diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 1d5714ea25..cd49011045 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -14,6 +14,66 @@ void SetGetD3DGSFrameCallback(GetGSFrameCb2 value) GetGSFrame = value; } +void DataHeap::Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type) +{ + m_size = heapSize; + D3D12_HEAP_DESC heapDesc = {}; + heapDesc.SizeInBytes = m_size; + heapDesc.Properties.Type = type; + heapDesc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; + 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.load(), getPos = m_getPos.load(); + 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.load(); + if (putPos + size < m_size) + { + m_putPos += powerOf2Align(size, 65536); + return putPos; + } + else + { + m_putPos.store(powerOf2Align(size, 65536)); + return 0; + } +} + +void DataHeap::Release() +{ +} + void D3D12GSRender::ResourceStorage::Reset() { m_vertexIndexBuffersHeapFreeSpace = 0; @@ -334,10 +394,13 @@ D3D12GSRender::D3D12GSRender() m_UAVHeap.m_getPos = 1024 * 1024 * 128 - 1; m_rtts.Init(m_device); + + m_constantsData.Init(m_device, 1024 * 1024, D3D12_HEAP_TYPE_UPLOAD); } D3D12GSRender::~D3D12GSRender() { + m_constantsData.Release(); m_UAVHeap.m_heap->Release(); m_readbackResources.m_heap->Release(); m_texturesRTTs.clear(); @@ -870,6 +933,13 @@ void D3D12GSRender::Flip() m_texturesCache.clear(); m_texturesRTTs.clear(); + for (auto tmp : m_constantsData.m_resourceStoredSinceLastSync) + { + std::get<2>(tmp)->Release(); + m_constantsData.m_getPos.store(std::get<0>(tmp)); + } + m_constantsData.m_resourceStoredSinceLastSync.clear(); + m_frame->Flip(nullptr); } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 80e3658444..e21b5f2415 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -44,6 +44,23 @@ typedef GSFrameBase2*(*GetGSFrameCb2)(); void SetGetD3DGSFrameCallback(GetGSFrameCb2 value); +struct DataHeap +{ + ID3D12Heap *m_heap; + size_t m_size; + std::atomic m_putPos, // Start of free space + m_getPos; // End of free space + std::vector > m_resourceStoredSinceLastSync; + + void Init(ID3D12Device *, size_t, D3D12_HEAP_TYPE); + /** + * Does alloc cross get position ? + */ + bool canAlloc(size_t size); + size_t alloc(size_t size); + void Release(); +}; + class D3D12GSRender : public GSRender { private: @@ -96,6 +113,8 @@ private: ResourceStorage m_perFrameStorage; + DataHeap m_constantsData; + struct UAVHeap { ID3D12Heap *m_heap;