diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 4043121785..7134278cf1 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -314,6 +314,7 @@ std::vector D3D12GSRender::UploadVertexBuffers(bool in else { ComPtr newVertexBuffer = createVertexBuffer(vbf, m_vertex_data, m_vertex_data_base_offset, m_device.Get(), m_vertexIndexData); + m_timers.m_bufferUploadSize += subBufferSize; vertexBuffer = newVertexBuffer.Get(); m_vertexCache[key] = newVertexBuffer.Get(); getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(newVertexBuffer); @@ -502,6 +503,8 @@ D3D12_INDEX_BUFFER_VIEW D3D12GSRender::uploadIndexBuffers(bool indexed_draw) indexBuffer->Unmap(0, nullptr); getCurrentResourceStorage().m_singleFrameLifetimeResources.push_back(indexBuffer); + m_timers.m_bufferUploadSize += subBufferSize; + indexBufferView.SizeInBytes = (UINT)subBufferSize; indexBufferView.BufferLocation = indexBuffer->GetGPUVirtualAddress(); return indexBufferView; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp index 046bcfce1a..ae590365ca 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.cpp @@ -383,8 +383,12 @@ void D3D12GSRender::Clear(u32 cmd) std::chrono::time_point startDuration = std::chrono::system_clock::now(); assert(cmd == NV4097_CLEAR_SURFACE); + std::chrono::time_point rttDurationStart = std::chrono::system_clock::now(); PrepareRenderTargets(getCurrentResourceStorage().m_commandList.Get()); + std::chrono::time_point rttDurationEnd = std::chrono::system_clock::now(); + m_timers.m_rttDuration += std::chrono::duration_cast(rttDurationEnd - rttDurationStart).count(); + /* if (m_set_color_mask) { glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); @@ -461,8 +465,15 @@ void D3D12GSRender::Clear(u32 cmd) void D3D12GSRender::Draw() { std::chrono::time_point startDuration = std::chrono::system_clock::now(); + + std::chrono::time_point rttDurationStart = std::chrono::system_clock::now(); PrepareRenderTargets(getCurrentResourceStorage().m_commandList.Get()); + std::chrono::time_point rttDurationEnd = std::chrono::system_clock::now(); + m_timers.m_rttDuration += std::chrono::duration_cast(rttDurationEnd - rttDurationStart).count(); + + std::chrono::time_point vertexIndexDurationStart = std::chrono::system_clock::now(); + // Init vertex count // TODO: Very hackish, clean this if (m_indexed_array.m_count) @@ -498,16 +509,24 @@ void D3D12GSRender::Draw() getCurrentResourceStorage().m_commandList->IASetIndexBuffer(&indexBufferView); } + std::chrono::time_point vertexIndexDurationEnd = std::chrono::system_clock::now(); + m_timers.m_vertexIndexDuration += std::chrono::duration_cast(vertexIndexDurationEnd - vertexIndexDurationStart).count(); + + std::chrono::time_point programLoadStart = std::chrono::system_clock::now(); if (!LoadProgram()) { LOG_ERROR(RSX, "LoadProgram failed."); Emu.Pause(); return; } + std::chrono::time_point programLoadEnd = std::chrono::system_clock::now(); + m_timers.m_programLoadDuration += std::chrono::duration_cast(programLoadEnd - programLoadStart).count(); getCurrentResourceStorage().m_commandList->SetGraphicsRootSignature(m_rootSignatures[m_PSO->second].Get()); getCurrentResourceStorage().m_commandList->OMSetStencilRef(m_stencil_func_ref); + std::chrono::time_point constantsDurationStart = std::chrono::system_clock::now(); + // Constants setScaleOffset(); getCurrentResourceStorage().m_commandList->SetDescriptorHeaps(1, getCurrentResourceStorage().m_scaleOffsetDescriptorHeap.GetAddressOf()); @@ -528,8 +547,13 @@ void D3D12GSRender::Draw() CD3DX12_GPU_DESCRIPTOR_HANDLE(getCurrentResourceStorage().m_constantsBufferDescriptorsHeap->GetGPUDescriptorHandleForHeapStart()) .Offset((INT)currentBufferIndex, g_descriptorStrideSRVCBVUAV) ); + + std::chrono::time_point constantsDurationEnd = std::chrono::system_clock::now(); + m_timers.m_constantsDuration += std::chrono::duration_cast(constantsDurationEnd - constantsDurationStart).count(); + getCurrentResourceStorage().m_commandList->SetPipelineState(m_PSO->first); + std::chrono::time_point textureDurationStart = std::chrono::system_clock::now(); if (m_PSO->second > 0) { size_t usedTexture = UploadTextures(getCurrentResourceStorage().m_commandList.Get()); @@ -577,6 +601,8 @@ void D3D12GSRender::Draw() getCurrentResourceStorage().m_currentTextureIndex += usedTexture; getCurrentResourceStorage().m_currentSamplerIndex += usedTexture; } + std::chrono::time_point textureDurationEnd = std::chrono::system_clock::now(); + m_timers.m_textureDuration += std::chrono::duration_cast(textureDurationEnd - textureDurationStart).count(); size_t numRTT; switch (m_surface_color_target) @@ -880,6 +906,12 @@ void D3D12GSRender::ResetTimer() { m_timers.m_drawCallCount = 0; m_timers.m_drawCallDuration = 0; + m_timers.m_rttDuration = 0; + m_timers.m_vertexIndexDuration = 0; + m_timers.m_bufferUploadSize = 0; + m_timers.m_programLoadDuration = 0; + m_timers.m_constantsDuration = 0; + m_timers.m_textureDuration = 0; } D3D12GSRender::ResourceStorage& D3D12GSRender::getCurrentResourceStorage() diff --git a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h index f19a1d3eeb..5ec6f886a3 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12GSRender.h @@ -240,6 +240,12 @@ private: { size_t m_drawCallDuration; size_t m_drawCallCount; + size_t m_rttDuration; + size_t m_vertexIndexDuration; + size_t m_bufferUploadSize; + size_t m_programLoadDuration; + size_t m_constantsDuration; + size_t m_textureDuration; } m_timers; void ResetTimer(); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp index d6c08375e1..4f05937e62 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Overlay.cpp @@ -117,7 +117,19 @@ void D3D12GSRender::ReleaseD2DStructures() void D3D12GSRender::renderOverlay() { D2D1_SIZE_F rtSize = m_d2dRenderTargets[m_swapChain->GetCurrentBackBufferIndex()]->GetSize(); - std::wstring duration = L"Draw duration : " + std::to_wstring(m_timers.m_drawCallDuration) + L" ms"; + std::wstring duration = L"Draw duration : " + std::to_wstring(m_timers.m_drawCallDuration) + L" us"; + float vtxIdxPercent = (float)m_timers.m_vertexIndexDuration / (float)m_timers.m_drawCallDuration; + std::wstring vertexIndexDuration = L"Vtx/Idx upload : " + std::to_wstring(m_timers.m_vertexIndexDuration) + L" us (" + std::to_wstring(100.f * vtxIdxPercent) + L" %)"; + std::wstring size = L"Upload size : " + std::to_wstring(m_timers.m_bufferUploadSize) + L" Bytes"; + float texPercent = (float)m_timers.m_textureDuration / (float)m_timers.m_drawCallDuration; + std::wstring texDuration = L"Textures : " + std::to_wstring(m_timers.m_textureDuration) + L" us (" + std::to_wstring(100.f * texPercent) + L" %)"; + float programPercent = (float)m_timers.m_programLoadDuration / (float)m_timers.m_drawCallDuration; + std::wstring programDuration = L"Program : " + std::to_wstring(m_timers.m_programLoadDuration) + L" us (" + std::to_wstring(100.f * programPercent) + L" %)"; + float constantsPercent = (float)m_timers.m_constantsDuration / (float)m_timers.m_drawCallDuration; + std::wstring constantDuration = L"Constants : " + std::to_wstring(m_timers.m_constantsDuration) + L" us (" + std::to_wstring(100.f * constantsPercent) + L" %)"; + float rttPercent = (float)m_timers.m_rttDuration / (float)m_timers.m_drawCallDuration; + std::wstring rttDuration = L"RTT : " + std::to_wstring(m_timers.m_rttDuration) + L" us (" + std::to_wstring(100.f * rttPercent) + L" %)"; + std::wstring count = L"Draw count : " + std::to_wstring(m_timers.m_drawCallCount); // Acquire our wrapped render target resource for the current back buffer. @@ -129,18 +141,60 @@ void D3D12GSRender::renderOverlay() m_d2dDeviceContext->SetTransform(D2D1::Matrix3x2F::Identity()); m_d2dDeviceContext->DrawTextW( duration.c_str(), - duration.size(), + (UINT32)duration.size(), m_textFormat.Get(), &D2D1::RectF(0, 0, rtSize.width, rtSize.height), m_textBrush.Get() ); m_d2dDeviceContext->DrawTextW( count.c_str(), - count.size(), + (UINT32)count.size(), m_textFormat.Get(), &D2D1::RectF(0, 14, rtSize.width, rtSize.height), m_textBrush.Get() ); + m_d2dDeviceContext->DrawTextW( + rttDuration.c_str(), + (UINT32)rttDuration.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 28, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->DrawTextW( + vertexIndexDuration.c_str(), + (UINT32)vertexIndexDuration.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 42, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->DrawTextW( + size.c_str(), + (UINT32)size.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 56, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->DrawTextW( + programDuration.c_str(), + (UINT32)programDuration.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 70, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->DrawTextW( + constantDuration.c_str(), + (UINT32)constantDuration.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 86, rtSize.width, rtSize.height), + m_textBrush.Get() + ); + m_d2dDeviceContext->DrawTextW( + texDuration.c_str(), + (UINT32)texDuration.size(), + m_textFormat.Get(), + &D2D1::RectF(0, 98, rtSize.width, rtSize.height), + m_textBrush.Get() + ); m_d2dDeviceContext->EndDraw(); // Release our wrapped render target resource. Releasing