1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-02-01 13:01:49 +01:00

d3d12: Support targetless flip

Fix PS3Doom
This commit is contained in:
vlj 2015-06-29 20:36:09 +02:00 committed by Vincent Lejeune
parent 725b0c606d
commit 265331117e
2 changed files with 155 additions and 79 deletions

View File

@ -89,6 +89,7 @@ void D3D12GSRender::ResourceStorage::Reset()
void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
{
m_RAMFramebuffer = nullptr;
m_frameFinishedHandle = 0;
// Create a global command allocator
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
@ -685,39 +686,113 @@ void D3D12GSRender::ExecCMD()
m_indexed_array.Reset();
}
void D3D12GSRender::Flip()
static bool
isFlipSurfaceInLocalMemory(u32 surfaceColorTarget)
{
ID3D12GraphicsCommandList *commandList;
m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, getCurrentResourceStorage().m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
getCurrentResourceStorage().m_inflightCommandList.push_back(commandList);
switch (m_surface_color_target)
switch (surfaceColorTarget)
{
case CELL_GCM_SURFACE_TARGET_0:
case CELL_GCM_SURFACE_TARGET_1:
case CELL_GCM_SURFACE_TARGET_MRT1:
case CELL_GCM_SURFACE_TARGET_MRT2:
case CELL_GCM_SURFACE_TARGET_MRT3:
return true;
case CELL_GCM_SURFACE_TARGET_NONE:
default:
return false;
}
}
void D3D12GSRender::Flip()
{
D3D12_RESOURCE_BARRIER barriers[2] = {};
barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barriers[0].Transition.pResource = m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()];
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
ID3D12GraphicsCommandList *commandList;
m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, getCurrentResourceStorage().m_commandAllocator, nullptr, IID_PPV_ARGS(&commandList));
getCurrentResourceStorage().m_inflightCommandList.push_back(commandList);
barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barriers[1].Transition.pResource = m_rtts.m_currentlyBoundRenderTargets[0];
barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ;
ID3D12Resource *resourceToFlip;
float viewport_w, viewport_h;
commandList->ResourceBarrier(2, barriers);
if (!isFlipSurfaceInLocalMemory(m_surface_color_target))
{
ResourceStorage &storage = getCurrentResourceStorage();
assert(storage.m_RAMFramebuffer == nullptr);
D3D12_HEAP_PROPERTIES heapProp = {};
heapProp.Type = D3D12_HEAP_TYPE_DEFAULT;
size_t w = 0, h = 0, rowPitch = 0;
ID3D12Resource *stagingTexture;
if (m_read_buffer)
{
CellGcmDisplayInfo* buffers = vm::get_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr);
u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL);
w = buffers[m_gcm_current_buffer].width;
h = buffers[m_gcm_current_buffer].height;
u8 *src_buffer = vm::get_ptr<u8>(addr);
rowPitch = align(w * 4, 256);
size_t textureSize = rowPitch * h; // * 4 for mipmap levels
assert(m_textureUploadData.canAlloc(textureSize));
size_t heapOffset = m_textureUploadData.alloc(textureSize);
check(m_device->CreatePlacedResource(
m_textureUploadData.m_heap,
heapOffset,
&getBufferResourceDesc(textureSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&stagingTexture)
));
m_textureUploadData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, textureSize, stagingTexture));
void *dstBuffer;
check(stagingTexture->Map(0, nullptr, &dstBuffer));
for (unsigned row = 0; row < h; row++)
memcpy((char*)dstBuffer + row * rowPitch, (char*)src_buffer + row * w * 4, w * 4);
stagingTexture->Unmap(0, nullptr);
}
check(
m_device->CreateCommittedResource(
&heapProp,
D3D12_HEAP_FLAG_NONE,
&getTexture2DResourceDesc(w, h, DXGI_FORMAT_R8G8B8A8_UNORM, 1),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&storage.m_RAMFramebuffer)
)
);
D3D12_TEXTURE_COPY_LOCATION src = {}, dst = {};
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dst.pResource = storage.m_RAMFramebuffer;
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.pResource = stagingTexture;
src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
src.PlacedFootprint.Footprint.Width = (UINT)w;
src.PlacedFootprint.Footprint.Height = (UINT)h;
src.PlacedFootprint.Footprint.Depth = (UINT)1;
src.PlacedFootprint.Footprint.RowPitch = rowPitch;
commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
commandList->ResourceBarrier(1, &getResourceBarrierTransition(storage.m_RAMFramebuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
resourceToFlip = storage.m_RAMFramebuffer;
viewport_w = (float)w, viewport_h = (float)h;
}
else
{
commandList->ResourceBarrier(1, &getResourceBarrierTransition(m_rtts.m_currentlyBoundRenderTargets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
resourceToFlip = m_rtts.m_currentlyBoundRenderTargets[0];
}
commandList->ResourceBarrier(1, &getResourceBarrierTransition(m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
D3D12_VIEWPORT viewport =
{
0.f,
0.f,
(float)RSXThread::m_width,
(float)RSXThread::m_height,
(float)m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()]->GetDesc().Width,
(float)m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()]->GetDesc().Height,
0.f,
1.f
};
@ -727,8 +802,8 @@ void D3D12GSRender::Flip()
{
0,
0,
(LONG)RSXThread::m_width,
(LONG)RSXThread::m_height,
(LONG)m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()]->GetDesc().Width,
(LONG)m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()]->GetDesc().Height,
};
commandList->RSSetScissorRects(1, &box);
commandList->SetGraphicsRootSignature(m_outputScalingPass.m_rootSignature);
@ -742,7 +817,7 @@ void D3D12GSRender::Flip()
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
m_device->CreateShaderResourceView(m_rtts.m_currentlyBoundRenderTargets[0], &srvDesc, CPUHandle);
m_device->CreateShaderResourceView(resourceToFlip, &srvDesc, CPUHandle);
D3D12_SAMPLER_DESC samplerDesc = {};
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
@ -774,15 +849,11 @@ void D3D12GSRender::Flip()
commandList->DrawInstanced(4, 1, 0, 0);
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_GENERIC_READ;
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
commandList->ResourceBarrier(2, barriers);
commandList->ResourceBarrier(1, &getResourceBarrierTransition(m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
if (isFlipSurfaceInLocalMemory(m_surface_color_target))
commandList->ResourceBarrier(1, &getResourceBarrierTransition(m_rtts.m_currentlyBoundRenderTargets[0], D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
check(commandList->Close());
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
}
}
check(m_swapChain->Present(Ini.GSVSyncEnable.GetValue() ? 1 : 0, 0));
// Add an event signaling queue completion
@ -822,6 +893,9 @@ void D3D12GSRender::Flip()
for (auto tmp : textoclean)
tmp->Release();
SAFE_RELEASE(storage.m_RAMFramebuffer);
storage.m_RAMFramebuffer = nullptr;
});
while (getCurrentResourceStorage().m_frameFinishedHandle)

View File

@ -313,6 +313,8 @@ private:
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
size_t m_currentTextureIndex;
ID3D12Resource *m_RAMFramebuffer;
void Reset();
void Init(ID3D12Device *device);
void Release();