1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 03:02:53 +01:00

d3d12: Rewrite per frame resource cleaning function.

This commit is contained in:
Vincent Lejeune 2015-08-16 00:20:08 +02:00 committed by Nekotekina
parent c2430d3af1
commit 63a54dd70d
4 changed files with 72 additions and 75 deletions

View File

@ -195,7 +195,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<ID3D12Heap, 65536> &vertexIndexHeap)
ComPtr<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
@ -204,14 +204,14 @@ ID3D12Resource *createVertexBuffer(const VertexBufferFormat &vbf, const RSXVerte
assert(vertexIndexHeap.canAlloc(subBufferSize));
size_t heapOffset = vertexIndexHeap.alloc(subBufferSize);
ID3D12Resource *vertexBuffer;
ComPtr<ID3D12Resource> 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<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::UploadVertexBuffers(bool in
vertexBuffer = It->second;
else
{
vertexBuffer = createVertexBuffer(vbf, m_vertex_data, m_device.Get(), m_vertexIndexData);
m_vertexCache[key] = vertexBuffer;
ComPtr<ID3D12Resource> 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<ID3D12Resource> 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));
}

View File

@ -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<ID3D12Resource *> &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<std::function<void()> > 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<std::mutex> lock(mut);
std::vector<ID3D12Resource *> 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<ID3D12Resource> 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);
});

View File

@ -122,7 +122,6 @@ struct DataHeap
size_t m_size;
size_t m_putPos; // Start of free space
std::atomic<size_t> m_getPos; // End of free space
std::vector<std::tuple<size_t, size_t, ID3D12Resource *> > 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<void()> getCleaningFunction()
size_t getCurrentPutPosMinusOne() const
{
std::atomic<size_t>& 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<ID3D12Resource> m_RAMFramebuffer;
// List of resources that can be freed after frame is flipped
std::vector<ComPtr<ID3D12Resource> > m_singleFrameLifetimeResources;
void Reset();
void Init(ID3D12Device *device);
void WaitAndClean(const std::vector<ID3D12Resource *> &dirtyTextures);
void Release();
};

View File

@ -395,7 +395,8 @@ ID3D12Resource *uploadSingleTexture(
const RSXTexture &texture,
ID3D12Device *device,
ID3D12GraphicsCommandList *commandList,
DataHeap<ID3D12Heap, 65536> &textureBuffersHeap)
DataHeap<ID3D12Heap, 65536> &textureBuffersHeap,
std::vector<ComPtr<ID3D12Resource> > &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<ID3D12Resource> 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<const u8>(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);