diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 19f84955c4..d33a678c5f 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -195,7 +195,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) +ComPtr 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 @@ -204,14 +204,14 @@ ID3D12Resource *createVertexBuffer(const VertexBufferFormat &vbf, const RSXVerte assert(vertexIndexHeap.canAlloc(subBufferSize)); size_t heapOffset = vertexIndexHeap.alloc(subBufferSize); - ID3D12Resource *vertexBuffer; + ComPtr vertexBuffer; ThrowIfFailed(device->CreatePlacedResource( vertexIndexHeap.m_heap, heapOffset, &getBufferResourceDesc(subBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, - IID_PPV_ARGS(&vertexBuffer) + IID_PPV_ARGS(vertexBuffer.GetAddressOf()) )); void *bufferMap; ThrowIfFailed(vertexBuffer->Map(0, nullptr, (void**)&bufferMap)); @@ -260,7 +260,6 @@ ID3D12Resource *createVertexBuffer(const VertexBufferFormat &vbf, const RSXVerte } vertexBuffer->Unmap(0, nullptr); - vertexIndexHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, subBufferSize, vertexBuffer)); return vertexBuffer; } @@ -302,8 +301,10 @@ std::vector D3D12GSRender::UploadVertexBuffers(bool in vertexBuffer = It->second; else { - vertexBuffer = createVertexBuffer(vbf, m_vertex_data, m_device.Get(), m_vertexIndexData); - m_vertexCache[key] = vertexBuffer; + ComPtr newVertexBuffer = createVertexBuffer(vbf, m_vertex_data, m_device.Get(), m_vertexIndexData); + vertexBuffer = newVertexBuffer.Get(); + m_vertexCache[key] = newVertexBuffer.Get(); + getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(newVertexBuffer); } D3D12_VERTEX_BUFFER_VIEW vertexBufferView = {}; @@ -404,14 +405,14 @@ D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw) assert(m_vertexIndexData.canAlloc(subBufferSize)); size_t heapOffset = m_vertexIndexData.alloc(subBufferSize); - ID3D12Resource *indexBuffer; + ComPtr indexBuffer; ThrowIfFailed(m_device->CreatePlacedResource( m_vertexIndexData.m_heap, heapOffset, &getBufferResourceDesc(subBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, - IID_PPV_ARGS(&indexBuffer) + IID_PPV_ARGS(indexBuffer.GetAddressOf()) )); void *bufferMap; @@ -461,7 +462,7 @@ D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw) } indexBuffer->Unmap(0, nullptr); - m_vertexIndexData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, subBufferSize, indexBuffer)); + getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(indexBuffer); indexBufferView.SizeInBytes = (UINT)subBufferSize; indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress(); @@ -512,7 +513,6 @@ void D3D12GSRender::setScaleOffset() 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, nullptr)); } void D3D12GSRender::FillVertexShaderConstantsBuffer() @@ -550,7 +550,6 @@ void D3D12GSRender::FillVertexShaderConstantsBuffer() 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, nullptr)); } void D3D12GSRender::FillPixelShaderConstantsBuffer() @@ -614,7 +613,6 @@ void D3D12GSRender::FillPixelShaderConstantsBuffer() 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, nullptr)); } diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index d41f31e60f..79bb06ee6f 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -104,6 +104,7 @@ void D3D12GSRender::ResourceStorage::Reset() m_commandAllocator->Reset(); m_inflightCommandList.clear(); + m_singleFrameLifetimeResources.clear(); } void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device) @@ -141,6 +142,19 @@ void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device) m_isUseable = true; } +void D3D12GSRender::ResourceStorage::WaitAndClean(const std::vector &dirtyTextures) +{ + WaitForSingleObjectEx(m_frameFinishedHandle, INFINITE, FALSE); + + Reset(); + + for (auto tmp : dirtyTextures) + tmp->Release(); + + m_RAMFramebuffer = nullptr; + m_isUseable.store(true, std::memory_order_release); +} + void D3D12GSRender::ResourceStorage::Release() { // NOTE: Should be released only after gfx pipeline last command has been finished. @@ -763,7 +777,7 @@ void D3D12GSRender::Flip() nullptr, IID_PPV_ARGS(&stagingTexture) )); - m_textureUploadData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, textureSize, stagingTexture)); + getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(stagingTexture); void *dstBuffer; ThrowIfFailed(stagingTexture->Map(0, nullptr, &dstBuffer)); @@ -897,12 +911,15 @@ void D3D12GSRender::Flip() m_vertexCache.clear(); m_vertexConstants.clear(); - std::vector > cleaningFunction = - { - m_constantsData.getCleaningFunction(), - m_vertexIndexData.getCleaningFunction(), - m_textureUploadData.getCleaningFunction(), - }; + + // Get the put pos - 1. This way after cleaning we can set the get ptr to + // this value, allowing heap to proceed even if we cleant before allocating + // a new value (that's the reason of the -1) + size_t newGetPosConstantsHeap = m_constantsData.getCurrentPutPosMinusOne(); + size_t newGetPosVertexIndexHeap = m_vertexIndexData.getCurrentPutPosMinusOne(); + size_t newGetPosTextureUploadHeap = m_textureUploadData.getCurrentPutPosMinusOne(); + size_t newGetPosReadbackHeap = m_readbackResources.getCurrentPutPosMinusOne(); + size_t newGetPosUAVHeap = m_UAVHeap.getCurrentPutPosMinusOne(); std::lock_guard lock(mut); std::vector textoclean = m_texToClean; @@ -910,20 +927,20 @@ void D3D12GSRender::Flip() storage.m_isUseable.store(false); - m_GC.pushWork([&, cleaningFunction, textoclean]() + m_GC.pushWork([&, + textoclean, + newGetPosConstantsHeap, + newGetPosVertexIndexHeap, + newGetPosTextureUploadHeap, + newGetPosReadbackHeap, + newGetPosUAVHeap]() { - WaitForSingleObjectEx(storage.m_frameFinishedHandle, INFINITE, FALSE); - - for (auto &cleanFunc : cleaningFunction) - cleanFunc(); - storage.Reset(); - - for (auto tmp : textoclean) - tmp->Release(); - - SAFE_RELEASE(storage.m_RAMFramebuffer); - storage.m_RAMFramebuffer = nullptr; - storage.m_isUseable.store(true, std::memory_order_release); + storage.WaitAndClean(textoclean); + m_constantsData.m_getPos.store(newGetPosConstantsHeap, std::memory_order_release); + m_vertexIndexData.m_getPos.store(newGetPosVertexIndexHeap, std::memory_order_release); + m_textureUploadData.m_getPos.store(newGetPosTextureUploadHeap, std::memory_order_release); + m_readbackResources.m_getPos.store(newGetPosReadbackHeap, std::memory_order_release); + m_UAVHeap.m_getPos.store(newGetPosUAVHeap, std::memory_order_release); }); while (!getCurrentResourceStorage().m_isUseable.load(std::memory_order_acquire)) @@ -990,7 +1007,7 @@ ID3D12Resource * D3D12GSRender::writeColorBuffer(ID3D12Resource * RTT, ID3D12Gra IID_PPV_ARGS(&Result) ) ); - m_readbackResources.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, sizeInByte, Result)); + getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(Result); cmdlist->ResourceBarrier(1, &getResourceBarrierTransition(RTT, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); @@ -1040,7 +1057,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) HANDLE handle = CreateEvent(0, FALSE, FALSE, 0); fence->SetEventOnCompletion(1, handle); - ID3D12Resource *writeDest, *depthConverted; + ComPtr writeDest, depthConverted; ID3D12GraphicsCommandList *convertCommandList; ID3D12DescriptorHeap *descriptorHeap; size_t depthRowPitch = m_surface_clip_w; @@ -1067,10 +1084,10 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) &resdesc, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, - IID_PPV_ARGS(&depthConverted) + IID_PPV_ARGS(depthConverted.GetAddressOf()) ) ); - m_UAVHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, sizeInByte, depthConverted)); + getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(depthConverted); sizeInByte = depthRowPitch * m_surface_clip_h; assert(m_readbackResources.canAlloc(sizeInByte)); @@ -1084,10 +1101,10 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) &resdesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, - IID_PPV_ARGS(&writeDest) + IID_PPV_ARGS(writeDest.GetAddressOf()) ) ); - m_readbackResources.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, sizeInByte, writeDest)); + getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(writeDest); ThrowIfFailed( m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, getCurrentResourceStorage().m_commandAllocator.Get(), nullptr, IID_PPV_ARGS(&convertCommandList)) @@ -1124,7 +1141,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; uavDesc.Format = DXGI_FORMAT_R8_UNORM; uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - m_device->CreateUnorderedAccessView(depthConverted, nullptr, &uavDesc, Handle); + m_device->CreateUnorderedAccessView(depthConverted.Get(), nullptr, &uavDesc, Handle); // Convert convertCommandList->ResourceBarrier(1, &getResourceBarrierTransition(m_rtts.m_currentlyBoundDepthStencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ)); @@ -1138,7 +1155,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) // Flush UAV D3D12_RESOURCE_BARRIER uavbarrier = {}; uavbarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - uavbarrier.UAV.pResource = depthConverted; + uavbarrier.UAV.pResource = depthConverted.Get(); D3D12_RESOURCE_BARRIER barriers[] = { @@ -1146,7 +1163,7 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) uavbarrier, }; convertCommandList->ResourceBarrier(2, barriers); - convertCommandList->ResourceBarrier(1, &getResourceBarrierTransition(depthConverted, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)); + convertCommandList->ResourceBarrier(1, &getResourceBarrierTransition(depthConverted.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE)); ThrowIfFailed(convertCommandList->Close()); m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&convertCommandList); @@ -1165,9 +1182,9 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) // Copy D3D12_TEXTURE_COPY_LOCATION dst = {}, src = {}; src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - src.pResource = depthConverted; + src.pResource = depthConverted.Get(); dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - dst.pResource = writeDest; + dst.pResource = writeDest.Get(); dst.PlacedFootprint.Offset = 0; dst.PlacedFootprint.Footprint.Depth = 1; dst.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8_UNORM; @@ -1228,10 +1245,6 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) //Wait for result m_commandQueueGraphic->Signal(fence, 1); - - auto depthUAVCleaning = m_UAVHeap.getCleaningFunction(); - auto readbackCleaning = m_readbackResources.getCleaningFunction(); - m_GC.pushWork([=]() { WaitForSingleObject(handle, INFINITE); CloseHandle(handle); @@ -1256,11 +1269,8 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) ptrAsChar[4 * (row * m_surface_clip_w + i) + 3] = c; } } - writeDest->Release(); - depthConverted->Release(); descriptorHeap->Release(); convertCommandList->Release(); - depthUAVCleaning(); } size_t srcPitch, dstPitch; @@ -1345,7 +1355,6 @@ void D3D12GSRender::semaphorePGRAPHBackendRelease(u32 offset, u32 value) if (needTransfer) downloadCommandList->Release(); - readbackCleaning(); vm::write32(m_label_addr + offset, value); }); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index 9bafb46f9b..09690d42cb 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -122,7 +122,6 @@ struct DataHeap size_t m_size; size_t m_putPos; // Start of free space std::atomic m_getPos; // End of free space - std::vector > m_resourceStoredSinceLastSync; void Init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags) { @@ -182,28 +181,14 @@ struct DataHeap void Release() { m_heap->Release(); - for (auto tmp : m_resourceStoredSinceLastSync) - { - SAFE_RELEASE(std::get<2>(tmp)); - } } /** - * Get a function that cleans heaps. - * It's caller responsability to ensure data are not used when executed. + * return current putpos - 1 */ - std::function getCleaningFunction() + size_t getCurrentPutPosMinusOne() const { - std::atomic& getPointer = m_getPos; - auto duplicatem_resourceStoredSinceLastSync = m_resourceStoredSinceLastSync; - m_resourceStoredSinceLastSync.clear(); - return [=, &getPointer]() { - for (auto tmp : duplicatem_resourceStoredSinceLastSync) - { - SAFE_RELEASE(std::get<2>(tmp)); - getPointer.exchange(std::get<0>(tmp)); - } - }; + return (m_putPos - 1 > 0) ? m_putPos - 1 : m_size - 1; } }; @@ -337,8 +322,12 @@ private: ComPtr m_RAMFramebuffer; + // List of resources that can be freed after frame is flipped + std::vector > m_singleFrameLifetimeResources; + void Reset(); void Init(ID3D12Device *device); + void WaitAndClean(const std::vector &dirtyTextures); void Release(); }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp index d6d5cb9ee4..48b38c1e84 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Texture.cpp @@ -395,7 +395,8 @@ ID3D12Resource *uploadSingleTexture( const RSXTexture &texture, ID3D12Device *device, ID3D12GraphicsCommandList *commandList, - DataHeap &textureBuffersHeap) + DataHeap &textureBuffersHeap, + std::vector > &stagingRamTexture) { ID3D12Resource *vramTexture; size_t w = texture.GetWidth(), h = texture.GetHeight(); @@ -550,7 +551,7 @@ ID3D12Resource *uploadSingleTexture( // Multiple of 256 size_t rowPitch = align(blockSizeInByte * widthInBlocks, 256); - ID3D12Resource *Texture; + ComPtr Texture; size_t textureSize = rowPitch * heightInBlocks * 2; // * 4 for mipmap levels assert(textureBuffersHeap.canAlloc(textureSize)); size_t heapOffset = textureBuffersHeap.alloc(textureSize); @@ -561,9 +562,9 @@ ID3D12Resource *uploadSingleTexture( &getBufferResourceDesc(textureSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, - IID_PPV_ARGS(&Texture) + IID_PPV_ARGS(Texture.GetAddressOf()) )); - textureBuffersHeap.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, textureSize, Texture)); + stagingRamTexture.push_back(Texture); auto pixels = vm::get_ptr(texaddr); void *textureData; @@ -633,7 +634,7 @@ ID3D12Resource *uploadSingleTexture( dst.SubresourceIndex = (UINT)miplevel; dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; src.PlacedFootprint.Offset = mli.offset; - src.pResource = Texture; + src.pResource = Texture.Get(); src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; src.PlacedFootprint.Footprint.Depth = 1; src.PlacedFootprint.Footprint.Width = (UINT)mli.width; @@ -758,7 +759,7 @@ size_t D3D12GSRender::UploadTextures(ID3D12GraphicsCommandList *cmdlist) } else { - vramTexture = uploadSingleTexture(m_textures[i], m_device.Get(), cmdlist, m_textureUploadData); + vramTexture = uploadSingleTexture(m_textures[i], m_device.Get(), cmdlist, m_textureUploadData, getCurrentResourceStorage().m_singleFrameLifetimeResources); m_texturesCache[texaddr] = vramTexture; u32 s = (u32)align(getTextureSize(m_textures[i]), 4096);