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:
parent
725b0c606d
commit
265331117e
@ -89,6 +89,7 @@ void D3D12GSRender::ResourceStorage::Reset()
|
|||||||
|
|
||||||
void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
void D3D12GSRender::ResourceStorage::Init(ID3D12Device *device)
|
||||||
{
|
{
|
||||||
|
m_RAMFramebuffer = nullptr;
|
||||||
m_frameFinishedHandle = 0;
|
m_frameFinishedHandle = 0;
|
||||||
// Create a global command allocator
|
// Create a global command allocator
|
||||||
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
|
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
|
||||||
@ -685,105 +686,175 @@ void D3D12GSRender::ExecCMD()
|
|||||||
m_indexed_array.Reset();
|
m_indexed_array.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12GSRender::Flip()
|
static bool
|
||||||
|
isFlipSurfaceInLocalMemory(u32 surfaceColorTarget)
|
||||||
{
|
{
|
||||||
ID3D12GraphicsCommandList *commandList;
|
switch (surfaceColorTarget)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
case CELL_GCM_SURFACE_TARGET_0:
|
case CELL_GCM_SURFACE_TARGET_0:
|
||||||
case CELL_GCM_SURFACE_TARGET_1:
|
case CELL_GCM_SURFACE_TARGET_1:
|
||||||
case CELL_GCM_SURFACE_TARGET_MRT1:
|
case CELL_GCM_SURFACE_TARGET_MRT1:
|
||||||
case CELL_GCM_SURFACE_TARGET_MRT2:
|
case CELL_GCM_SURFACE_TARGET_MRT2:
|
||||||
case CELL_GCM_SURFACE_TARGET_MRT3:
|
case CELL_GCM_SURFACE_TARGET_MRT3:
|
||||||
|
return true;
|
||||||
|
case CELL_GCM_SURFACE_TARGET_NONE:
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D12GSRender::Flip()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
ID3D12Resource *resourceToFlip;
|
||||||
|
float viewport_w, viewport_h;
|
||||||
|
|
||||||
|
if (!isFlipSurfaceInLocalMemory(m_surface_color_target))
|
||||||
{
|
{
|
||||||
D3D12_RESOURCE_BARRIER barriers[2] = {};
|
ResourceStorage &storage = getCurrentResourceStorage();
|
||||||
barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
assert(storage.m_RAMFramebuffer == nullptr);
|
||||||
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;
|
|
||||||
|
|
||||||
barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
D3D12_HEAP_PROPERTIES heapProp = {};
|
||||||
barriers[1].Transition.pResource = m_rtts.m_currentlyBoundRenderTargets[0];
|
heapProp.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
|
||||||
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_GENERIC_READ;
|
|
||||||
|
|
||||||
commandList->ResourceBarrier(2, barriers);
|
size_t w = 0, h = 0, rowPitch = 0;
|
||||||
|
|
||||||
D3D12_VIEWPORT viewport =
|
ID3D12Resource *stagingTexture;
|
||||||
|
if (m_read_buffer)
|
||||||
{
|
{
|
||||||
0.f,
|
CellGcmDisplayInfo* buffers = vm::get_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr);
|
||||||
0.f,
|
u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||||
(float)RSXThread::m_width,
|
w = buffers[m_gcm_current_buffer].width;
|
||||||
(float)RSXThread::m_height,
|
h = buffers[m_gcm_current_buffer].height;
|
||||||
0.f,
|
u8 *src_buffer = vm::get_ptr<u8>(addr);
|
||||||
1.f
|
|
||||||
};
|
|
||||||
commandList->RSSetViewports(1, &viewport);
|
|
||||||
|
|
||||||
D3D12_RECT box =
|
rowPitch = align(w * 4, 256);
|
||||||
{
|
size_t textureSize = rowPitch * h; // * 4 for mipmap levels
|
||||||
0,
|
assert(m_textureUploadData.canAlloc(textureSize));
|
||||||
0,
|
size_t heapOffset = m_textureUploadData.alloc(textureSize);
|
||||||
(LONG)RSXThread::m_width,
|
|
||||||
(LONG)RSXThread::m_height,
|
|
||||||
};
|
|
||||||
commandList->RSSetScissorRects(1, &box);
|
|
||||||
commandList->SetGraphicsRootSignature(m_outputScalingPass.m_rootSignature);
|
|
||||||
commandList->SetPipelineState(m_outputScalingPass.m_PSO);
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle;
|
|
||||||
CPUHandle = m_outputScalingPass.m_textureDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
|
||||||
CPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) * m_swapChain->GetCurrentBackBufferIndex();
|
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
|
||||||
// FIXME: Not always true
|
|
||||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
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);
|
|
||||||
|
|
||||||
D3D12_SAMPLER_DESC samplerDesc = {};
|
check(m_device->CreatePlacedResource(
|
||||||
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
m_textureUploadData.m_heap,
|
||||||
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
heapOffset,
|
||||||
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
&getBufferResourceDesc(textureSize),
|
||||||
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||||
CPUHandle = m_outputScalingPass.m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
nullptr,
|
||||||
CPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) * m_swapChain->GetCurrentBackBufferIndex();
|
IID_PPV_ARGS(&stagingTexture)
|
||||||
m_device->CreateSampler(&samplerDesc, CPUHandle);
|
));
|
||||||
|
m_textureUploadData.m_resourceStoredSinceLastSync.push_back(std::make_tuple(heapOffset, textureSize, stagingTexture));
|
||||||
|
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle;
|
void *dstBuffer;
|
||||||
GPUHandle = m_outputScalingPass.m_textureDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
check(stagingTexture->Map(0, nullptr, &dstBuffer));
|
||||||
GPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) * m_swapChain->GetCurrentBackBufferIndex();
|
for (unsigned row = 0; row < h; row++)
|
||||||
commandList->SetDescriptorHeaps(1, &m_outputScalingPass.m_textureDescriptorHeap);
|
memcpy((char*)dstBuffer + row * rowPitch, (char*)src_buffer + row * w * 4, w * 4);
|
||||||
commandList->SetGraphicsRootDescriptorTable(0, GPUHandle);
|
stagingTexture->Unmap(0, nullptr);
|
||||||
GPUHandle = m_outputScalingPass.m_samplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
}
|
||||||
GPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) * m_swapChain->GetCurrentBackBufferIndex();
|
|
||||||
commandList->SetDescriptorHeaps(1, &m_outputScalingPass.m_samplerDescriptorHeap);
|
|
||||||
commandList->SetGraphicsRootDescriptorTable(1, GPUHandle);
|
|
||||||
|
|
||||||
CPUHandle = m_backbufferAsRendertarget[m_swapChain->GetCurrentBackBufferIndex()]->GetCPUDescriptorHandleForHeapStart();
|
check(
|
||||||
commandList->OMSetRenderTargets(1, &CPUHandle, true, nullptr);
|
m_device->CreateCommittedResource(
|
||||||
D3D12_VERTEX_BUFFER_VIEW vbv = {};
|
&heapProp,
|
||||||
vbv.BufferLocation = m_outputScalingPass.m_vertexBuffer->GetGPUVirtualAddress();
|
D3D12_HEAP_FLAG_NONE,
|
||||||
vbv.StrideInBytes = 4 * sizeof(float);
|
&getTexture2DResourceDesc(w, h, DXGI_FORMAT_R8G8B8A8_UNORM, 1),
|
||||||
vbv.SizeInBytes = 16 * sizeof(float);
|
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
commandList->IASetVertexBuffers(0, 1, &vbv);
|
nullptr,
|
||||||
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
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->DrawInstanced(4, 1, 0, 0);
|
commandList->ResourceBarrier(1, &getResourceBarrierTransition(storage.m_RAMFramebuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
|
||||||
|
resourceToFlip = storage.m_RAMFramebuffer;
|
||||||
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
viewport_w = (float)w, viewport_h = (float)h;
|
||||||
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);
|
|
||||||
check(commandList->Close());
|
|
||||||
m_commandQueueGraphic->ExecuteCommandLists(1, (ID3D12CommandList**)&commandList);
|
|
||||||
}
|
}
|
||||||
|
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)m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()]->GetDesc().Width,
|
||||||
|
(float)m_backBuffer[m_swapChain->GetCurrentBackBufferIndex()]->GetDesc().Height,
|
||||||
|
0.f,
|
||||||
|
1.f
|
||||||
|
};
|
||||||
|
commandList->RSSetViewports(1, &viewport);
|
||||||
|
|
||||||
|
D3D12_RECT box =
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(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);
|
||||||
|
commandList->SetPipelineState(m_outputScalingPass.m_PSO);
|
||||||
|
D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle;
|
||||||
|
CPUHandle = m_outputScalingPass.m_textureDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||||
|
CPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) * m_swapChain->GetCurrentBackBufferIndex();
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||||
|
// FIXME: Not always true
|
||||||
|
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srvDesc.Texture2D.MipLevels = 1;
|
||||||
|
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||||
|
m_device->CreateShaderResourceView(resourceToFlip, &srvDesc, CPUHandle);
|
||||||
|
|
||||||
|
D3D12_SAMPLER_DESC samplerDesc = {};
|
||||||
|
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
|
||||||
|
samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
|
samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
|
samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||||
|
CPUHandle = m_outputScalingPass.m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
|
||||||
|
CPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) * m_swapChain->GetCurrentBackBufferIndex();
|
||||||
|
m_device->CreateSampler(&samplerDesc, CPUHandle);
|
||||||
|
|
||||||
|
D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle;
|
||||||
|
GPUHandle = m_outputScalingPass.m_textureDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||||
|
GPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) * m_swapChain->GetCurrentBackBufferIndex();
|
||||||
|
commandList->SetDescriptorHeaps(1, &m_outputScalingPass.m_textureDescriptorHeap);
|
||||||
|
commandList->SetGraphicsRootDescriptorTable(0, GPUHandle);
|
||||||
|
GPUHandle = m_outputScalingPass.m_samplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||||
|
GPUHandle.ptr += m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) * m_swapChain->GetCurrentBackBufferIndex();
|
||||||
|
commandList->SetDescriptorHeaps(1, &m_outputScalingPass.m_samplerDescriptorHeap);
|
||||||
|
commandList->SetGraphicsRootDescriptorTable(1, GPUHandle);
|
||||||
|
|
||||||
|
CPUHandle = m_backbufferAsRendertarget[m_swapChain->GetCurrentBackBufferIndex()]->GetCPUDescriptorHandleForHeapStart();
|
||||||
|
commandList->OMSetRenderTargets(1, &CPUHandle, true, nullptr);
|
||||||
|
D3D12_VERTEX_BUFFER_VIEW vbv = {};
|
||||||
|
vbv.BufferLocation = m_outputScalingPass.m_vertexBuffer->GetGPUVirtualAddress();
|
||||||
|
vbv.StrideInBytes = 4 * sizeof(float);
|
||||||
|
vbv.SizeInBytes = 16 * sizeof(float);
|
||||||
|
commandList->IASetVertexBuffers(0, 1, &vbv);
|
||||||
|
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||||
|
|
||||||
|
commandList->DrawInstanced(4, 1, 0, 0);
|
||||||
|
|
||||||
|
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));
|
check(m_swapChain->Present(Ini.GSVSyncEnable.GetValue() ? 1 : 0, 0));
|
||||||
// Add an event signaling queue completion
|
// Add an event signaling queue completion
|
||||||
|
|
||||||
@ -822,6 +893,9 @@ void D3D12GSRender::Flip()
|
|||||||
|
|
||||||
for (auto tmp : textoclean)
|
for (auto tmp : textoclean)
|
||||||
tmp->Release();
|
tmp->Release();
|
||||||
|
|
||||||
|
SAFE_RELEASE(storage.m_RAMFramebuffer);
|
||||||
|
storage.m_RAMFramebuffer = nullptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
while (getCurrentResourceStorage().m_frameFinishedHandle)
|
while (getCurrentResourceStorage().m_frameFinishedHandle)
|
||||||
|
@ -313,6 +313,8 @@ private:
|
|||||||
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
|
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
|
||||||
size_t m_currentTextureIndex;
|
size_t m_currentTextureIndex;
|
||||||
|
|
||||||
|
ID3D12Resource *m_RAMFramebuffer;
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Init(ID3D12Device *device);
|
void Init(ID3D12Device *device);
|
||||||
void Release();
|
void Release();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user