mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
perf: 避免多余栅栏
This commit is contained in:
parent
4d99b18cfc
commit
4326dc627c
7 changed files with 60 additions and 45 deletions
|
|
@ -126,7 +126,8 @@ void FrameProducer::_ThreadProc(
|
|||
}
|
||||
}
|
||||
|
||||
// 不能在缩放线程释放
|
||||
_graphicsContext.WaitForGpu();
|
||||
// 必须在创建线程释放
|
||||
_frameSource.reset();
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +158,7 @@ bool FrameProducer::_Initialize(
|
|||
}
|
||||
|
||||
const uint32_t maxInFlightFrameCount = ScalingWindow::Get().Options().maxProducerInFlightFrames;
|
||||
if (!_graphicsContext.Initialize(device, maxInFlightFrameCount, D3D12_COMMAND_LIST_TYPE_COMPUTE)) {
|
||||
if (!_graphicsContext.Initialize(device, maxInFlightFrameCount, D3D12_COMMAND_LIST_TYPE_COMPUTE, true)) {
|
||||
Logger::Get().Error("初始化 GraphicsContext 失败");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
#include "Logger.h"
|
||||
#include "DirectXHelper.h"
|
||||
#include "StrHelper.h"
|
||||
#include <d3dkmthk.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
bool GraphicsContext::Initialize(
|
||||
const GraphicsCardId& graphicsCardId,
|
||||
uint32_t maxInFlightFrameCount,
|
||||
D3D12_COMMAND_LIST_TYPE commandListType
|
||||
D3D12_COMMAND_LIST_TYPE commandListType,
|
||||
bool disableFrameFenceTracking
|
||||
) noexcept {
|
||||
HRESULT hr = _CreateDXGIFactory();
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -23,7 +23,7 @@ bool GraphicsContext::Initialize(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!_InitializeDeviceResources(maxInFlightFrameCount, commandListType)) {
|
||||
if (!_InitializeDeviceResources(maxInFlightFrameCount, commandListType, disableFrameFenceTracking)) {
|
||||
Logger::Get().Error("_InitializeDeviceResources 失败");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -34,7 +34,8 @@ bool GraphicsContext::Initialize(
|
|||
bool GraphicsContext::Initialize(
|
||||
ID3D12Device5* device,
|
||||
uint32_t maxInFlightFrameCount,
|
||||
D3D12_COMMAND_LIST_TYPE commandListType
|
||||
D3D12_COMMAND_LIST_TYPE commandListType,
|
||||
bool disableFrameFenceTracking
|
||||
) noexcept {
|
||||
_device.copy_from(device);
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ bool GraphicsContext::Initialize(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!_InitializeDeviceResources(maxInFlightFrameCount, commandListType)) {
|
||||
if (!_InitializeDeviceResources(maxInFlightFrameCount, commandListType, disableFrameFenceTracking)) {
|
||||
Logger::Get().Error("_InitializeDeviceResources 失败");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -81,7 +82,7 @@ HRESULT GraphicsContext::WaitForFenceValue(uint64_t fenceValue) noexcept {
|
|||
}
|
||||
}
|
||||
|
||||
HRESULT GraphicsContext::WaitForGPU() noexcept {
|
||||
HRESULT GraphicsContext::WaitForGpu() noexcept {
|
||||
HRESULT hr = _commandQueue->Signal(_fence.get(), ++_curFenceValue);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
|
@ -91,12 +92,14 @@ HRESULT GraphicsContext::WaitForGPU() noexcept {
|
|||
}
|
||||
|
||||
HRESULT GraphicsContext::BeginFrame(uint32_t& curFrameIndex, ID3D12PipelineState* initialState) noexcept {
|
||||
HRESULT hr = WaitForFenceValue(_frameFenceValues[_curFrameIndex]);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
if (!_frameFenceValues.empty()) {
|
||||
HRESULT hr = WaitForFenceValue(_frameFenceValues[_curFrameIndex]);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = _commandAllocators[_curFrameIndex]->Reset();
|
||||
HRESULT hr = _commandAllocators[_curFrameIndex]->Reset();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -111,9 +114,11 @@ HRESULT GraphicsContext::BeginFrame(uint32_t& curFrameIndex, ID3D12PipelineState
|
|||
}
|
||||
|
||||
HRESULT GraphicsContext::EndFrame() noexcept {
|
||||
HRESULT hr = Signal(_frameFenceValues[_curFrameIndex]);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
if (!_frameFenceValues.empty()) {
|
||||
HRESULT hr = Signal(_frameFenceValues[_curFrameIndex]);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
_curFrameIndex = (_curFrameIndex + 1) % (uint32_t)_commandAllocators.size();
|
||||
|
|
@ -132,7 +137,11 @@ HRESULT GraphicsContext::_CreateDXGIFactory() noexcept {
|
|||
return hr;
|
||||
}
|
||||
|
||||
bool GraphicsContext::_InitializeDeviceResources(uint32_t maxInFlightFrameCount, D3D12_COMMAND_LIST_TYPE commandListType) noexcept {
|
||||
bool GraphicsContext::_InitializeDeviceResources(
|
||||
uint32_t maxInFlightFrameCount,
|
||||
D3D12_COMMAND_LIST_TYPE commandListType,
|
||||
bool disableFrameFenceTracking
|
||||
) noexcept {
|
||||
// 检查根签名版本
|
||||
{
|
||||
D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = { .HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1 };
|
||||
|
|
@ -178,7 +187,10 @@ bool GraphicsContext::_InitializeDeviceResources(uint32_t maxInFlightFrameCount,
|
|||
return false;
|
||||
}
|
||||
|
||||
_frameFenceValues.resize(maxInFlightFrameCount);
|
||||
// 如果已在外部同步则无需追踪每帧的栅栏值
|
||||
if (!disableFrameFenceTracking) {
|
||||
_frameFenceValues.resize(maxInFlightFrameCount);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -280,17 +292,6 @@ bool GraphicsContext::_CreateAdapterAndDevice(const GraphicsCardId& graphicsCard
|
|||
return true;
|
||||
}
|
||||
|
||||
static void SetGpuPriority() noexcept {
|
||||
// 来自 https://github.com/obsproject/obs-studio/blob/16cb051a57bb357fe866252c1360ce2c38e2deec/libobs-d3d11/d3d11-subsystem.cpp#L429
|
||||
// 不使用 REALTIME 优先级,它会造成系统不稳定,而且可能会导致源窗口卡顿。
|
||||
// OBS 还调用了 SetGPUThreadPriority,但这个接口似乎无用。
|
||||
NTSTATUS status = D3DKMTSetProcessSchedulingPriorityClass(
|
||||
GetCurrentProcess(), D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
Logger::Get().NTError("D3DKMTSetProcessSchedulingPriorityClass 失败", status);
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsContext::_TryCreateD3DDevice(const winrt::com_ptr<IDXGIAdapter1>& adapter, const DXGI_ADAPTER_DESC1& adapterDesc) noexcept {
|
||||
HRESULT hr = D3D12CreateDevice(adapter.get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&_device));
|
||||
if (FAILED(hr)) {
|
||||
|
|
@ -348,9 +349,6 @@ bool GraphicsContext::_TryCreateD3DDevice(const winrt::com_ptr<IDXGIAdapter1>& a
|
|||
Logger::Get().Info(fmt::format("当前图形适配器: \n\tVendorId: {:#x}\n\tDeviceId: {:#x}\n\tDescription: {}",
|
||||
adapterDesc.VendorId, adapterDesc.DeviceId, StrHelper::UTF16ToUTF8(adapterDesc.Description)));
|
||||
|
||||
// 每次创建 D3D 设备后尝试提高 GPU 优先级,OBS 也是这么做的
|
||||
SetGpuPriority();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,13 +12,15 @@ public:
|
|||
bool Initialize(
|
||||
const GraphicsCardId& graphicsCardId,
|
||||
uint32_t maxInFlightFrameCount,
|
||||
D3D12_COMMAND_LIST_TYPE commandListType
|
||||
D3D12_COMMAND_LIST_TYPE commandListType,
|
||||
bool disableFrameFenceTracking = false
|
||||
) noexcept;
|
||||
|
||||
bool Initialize(
|
||||
ID3D12Device5* device,
|
||||
uint32_t maxInFlightFrameCount,
|
||||
D3D12_COMMAND_LIST_TYPE commandListType
|
||||
D3D12_COMMAND_LIST_TYPE commandListType,
|
||||
bool disableFrameTracking = false
|
||||
) noexcept;
|
||||
|
||||
IDXGIFactory7* GetDXGIFactory() const noexcept {
|
||||
|
|
@ -55,7 +57,7 @@ public:
|
|||
|
||||
HRESULT WaitForFenceValue(uint64_t fenceValue) noexcept;
|
||||
|
||||
HRESULT WaitForGPU() noexcept;
|
||||
HRESULT WaitForGpu() noexcept;
|
||||
|
||||
HRESULT BeginFrame(
|
||||
uint32_t& curFrameIndex,
|
||||
|
|
@ -67,7 +69,11 @@ public:
|
|||
private:
|
||||
HRESULT _CreateDXGIFactory() noexcept;
|
||||
|
||||
bool _InitializeDeviceResources(uint32_t maxInFlightFrameCount, D3D12_COMMAND_LIST_TYPE commandListType) noexcept;
|
||||
bool _InitializeDeviceResources(
|
||||
uint32_t maxInFlightFrameCount,
|
||||
D3D12_COMMAND_LIST_TYPE commandListType,
|
||||
bool disableFrameFenceTracking
|
||||
) noexcept;
|
||||
|
||||
bool _CreateAdapterAndDevice(const GraphicsCardId& graphicsCardId) noexcept;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,18 +6,28 @@
|
|||
#include "ScalingWindow.h"
|
||||
#include "SwapChainPresenter.h"
|
||||
#include "GraphicsCaptureFrameSource2.h"
|
||||
#include <d3dkmthk.h>
|
||||
#include <windows.graphics.display.interop.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
static constexpr HRESULT S_RECOVERED = CommonSharedConstants::S_RECOVERED;
|
||||
|
||||
static constexpr float SCENE_REFERRED_SDR_WHITE_LEVEL = (float)CommonSharedConstants::SCENE_REFERRED_SDR_WHITE_LEVEL;
|
||||
|
||||
Renderer2::Renderer2() noexcept {}
|
||||
|
||||
Renderer2::~Renderer2() noexcept {
|
||||
_graphicsContext.WaitForGPU();
|
||||
_graphicsContext.WaitForGpu();
|
||||
}
|
||||
|
||||
static void SetGpuPriority() noexcept {
|
||||
// 来自 https://github.com/obsproject/obs-studio/blob/16cb051a57bb357fe866252c1360ce2c38e2deec/libobs-d3d11/d3d11-subsystem.cpp#L429
|
||||
// 不使用 REALTIME 优先级,它会造成系统不稳定,而且可能会导致源窗口卡顿。
|
||||
// OBS 还调用了 SetGPUThreadPriority,但这个接口似乎无用。
|
||||
NTSTATUS status = D3DKMTSetProcessSchedulingPriorityClass(
|
||||
GetCurrentProcess(), D3DKMT_SCHEDULINGPRIORITYCLASS_HIGH);
|
||||
if (status != STATUS_SUCCESS) {
|
||||
Logger::Get().NTError("D3DKMTSetProcessSchedulingPriorityClass 失败", status);
|
||||
}
|
||||
}
|
||||
|
||||
ScalingError Renderer2::Initialize(
|
||||
|
|
@ -30,11 +40,14 @@ ScalingError Renderer2::Initialize(
|
|||
_hCurMonitor = hMonitor;
|
||||
|
||||
const ScalingOptions& options = ScalingWindow::Get().Options();
|
||||
if (FAILED(_graphicsContext.Initialize(options.graphicsCardId, options.Is3DGameMode() ? 4 : 8, D3D12_COMMAND_LIST_TYPE_DIRECT))) {
|
||||
if (!_graphicsContext.Initialize(options.graphicsCardId, options.Is3DGameMode() ? 4 : 8, D3D12_COMMAND_LIST_TYPE_DIRECT)) {
|
||||
Logger::Get().Error("初始化 GraphicsContext 失败");
|
||||
return ScalingError::ScalingFailedGeneral;
|
||||
}
|
||||
|
||||
// 每次创建 D3D 设备后尝试提高 GPU 优先级,OBS 也是这么做的
|
||||
SetGpuPriority();
|
||||
|
||||
// 失败则回落到使用传统方法获取颜色显示能力
|
||||
_TryInitDisplayInfo();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "pch.h"
|
||||
#include "SharedRingBuffer.h"
|
||||
#include "GraphicsContext.h"
|
||||
#include "Logger.h"
|
||||
#include "ScalingWindow.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
namespace Magpie {
|
||||
|
||||
static constexpr uint32_t BUFFER_COUNT_DURING_RESIZE = 2;
|
||||
|
||||
bool SwapChainPresenter::Initialize(
|
||||
GraphicsContext& graphicContext,
|
||||
HWND hwndAttach,
|
||||
|
|
@ -204,7 +202,7 @@ HRESULT SwapChainPresenter::EndFrame() noexcept {
|
|||
// 实用价值。
|
||||
|
||||
// 等待渲染完成
|
||||
HRESULT hr = _graphicContext->WaitForGPU();
|
||||
HRESULT hr = _graphicContext->WaitForGpu();
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("GraphicsContext::WaitForGPU", hr);
|
||||
return hr;
|
||||
|
|
@ -278,7 +276,7 @@ HRESULT SwapChainPresenter::OnColorInfoChanged(const ColorInfo& colorInfo) noexc
|
|||
}
|
||||
|
||||
HRESULT SwapChainPresenter::_RecreateBuffers() noexcept {
|
||||
HRESULT hr = _graphicContext->WaitForGPU();
|
||||
HRESULT hr = _graphicContext->WaitForGpu();
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("GraphicsContext::WaitForGPU", hr);
|
||||
return hr;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static void InitializeDirectX() noexcept {
|
|||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
debugController->EnableDebugLayer();
|
||||
// 启用 GPU-based validation,但会产生警告消息,而且这个消息无法轻易禁用
|
||||
debugController->SetEnableGPUBasedValidation(TRUE);
|
||||
// debugController->SetEnableGPUBasedValidation(TRUE);
|
||||
|
||||
// Win11 开始支持生成默认名字,包含资源的基本属性
|
||||
if (winrt::com_ptr<ID3D12Debug5> debugController5 = debugController.try_as<ID3D12Debug5>()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue