mirror of
https://github.com/Blinue/Magpie.git
synced 2026-06-24 02:04:10 +00:00
feat: 实现 WGC (p1)
This commit is contained in:
parent
51e1cc856f
commit
44410b667e
5 changed files with 426 additions and 16 deletions
|
|
@ -1,19 +1,378 @@
|
|||
#include "pch.h"
|
||||
#include "GraphicsCaptureFrameSource2.h"
|
||||
#include "Logger.h"
|
||||
#include "Win32Helper.h"
|
||||
#include "ScalingWindow.h"
|
||||
#include <dwmapi.h>
|
||||
#include <windows.graphics.directx.direct3d11.interop.h>
|
||||
|
||||
namespace winrt {
|
||||
using namespace Windows::Graphics;
|
||||
using namespace Windows::Graphics::Capture;
|
||||
using namespace Windows::Graphics::DirectX;
|
||||
using namespace Windows::Graphics::DirectX::Direct3D11;
|
||||
}
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
bool GraphicsCaptureFrameSource2::Initialize(
|
||||
ID3D12Device5* /*device*/,
|
||||
ID3D12CommandList* /*commandList*/,
|
||||
HMONITOR /*hMonSrc*/,
|
||||
bool /*useScRGB*/
|
||||
) noexcept {
|
||||
GraphicsCaptureFrameSource2::~GraphicsCaptureFrameSource2() {
|
||||
_StopCapture();
|
||||
}
|
||||
|
||||
static winrt::com_ptr<IDXGIAdapter1> FindAdapterOfMonitor(IDXGIFactory7* dxgiFactory, HMONITOR hMon) noexcept {
|
||||
winrt::com_ptr<IDXGIAdapter1> adapter;
|
||||
winrt::com_ptr<IDXGIOutput> output;
|
||||
for (UINT adapterIdx = 0;
|
||||
SUCCEEDED(dxgiFactory->EnumAdapters1(adapterIdx, adapter.put()));
|
||||
++adapterIdx
|
||||
) {
|
||||
for (UINT outputIdx = 0;
|
||||
SUCCEEDED(adapter->EnumOutputs(outputIdx, output.put()));
|
||||
++outputIdx
|
||||
) {
|
||||
DXGI_OUTPUT_DESC desc;
|
||||
if (SUCCEEDED(output->GetDesc(&desc)) && desc.Monitor == hMon) {
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adapter = nullptr;
|
||||
return adapter;
|
||||
}
|
||||
|
||||
static bool CalcWindowCapturedFrameBounds(HWND hWnd, RECT& rect) noexcept {
|
||||
// Graphics Capture 的捕获区域没有文档记录,这里的计算是我实验了多种窗口后得出的,
|
||||
// 高度依赖实现细节,未来可能会失效。
|
||||
// Win10 和 Win11 24H2 开始捕获区域为 extended frame bounds;Win11 24H2 前
|
||||
// DwmGetWindowAttribute 对最大化的窗口返回值和 Win10 不同,可能是 OS 的 bug,
|
||||
// 应进一步处理。
|
||||
const auto& srcTracker = ScalingWindow::Get().SrcTracker();
|
||||
rect = srcTracker.WindowFrameRect();
|
||||
|
||||
if (!srcTracker.IsZoomed() ||
|
||||
Win32Helper::GetOSVersion().IsWin10() ||
|
||||
Win32Helper::GetOSVersion().Is24H2OrNewer()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果窗口禁用了非客户区域绘制则捕获区域为 extended frame bounds
|
||||
BOOL hasBorder = TRUE;
|
||||
HRESULT hr = DwmGetWindowAttribute(hWnd, DWMWA_NCRENDERING_ENABLED, &hasBorder, sizeof(hasBorder));
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("DwmGetWindowAttribute 失败", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasBorder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RECT clientRect;
|
||||
if (!Win32Helper::GetClientScreenRect(hWnd, clientRect)) {
|
||||
Logger::Get().Error("GetClientScreenRect 失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 有些窗口最大化后有部分客户区在屏幕外,如 UWP 和资源管理器,它们的捕获区域
|
||||
// 是整个客户区。否则捕获区域不会超出屏幕
|
||||
HMONITOR hMon = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO mi{ .cbSize = sizeof(mi) };
|
||||
if (!GetMonitorInfo(hMon, &mi)) {
|
||||
Logger::Get().Win32Error("GetMonitorInfo 失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (clientRect.top < mi.rcWork.top) {
|
||||
rect = clientRect;
|
||||
} else {
|
||||
Win32Helper::IntersectRect(rect, rect, mi.rcWork);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FrameSourceState GraphicsCaptureFrameSource2::Update() noexcept {
|
||||
bool GraphicsCaptureFrameSource2::Initialize(
|
||||
ID3D12Device5* device,
|
||||
ID3D12CommandList* /*commandList*/,
|
||||
IDXGIFactory7* dxgiFactory,
|
||||
IDXGIAdapter4* dxgiAdapter,
|
||||
HMONITOR hMonSrc,
|
||||
bool /*useScRGB*/
|
||||
) noexcept {
|
||||
assert(hMonSrc);
|
||||
|
||||
if (!winrt::GraphicsCaptureSession::IsSupported()) {
|
||||
Logger::Get().Error("当前无法使用 Graphics Capture");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找源窗口所在屏幕连接的适配器
|
||||
winrt::com_ptr<IDXGIAdapter1> srcMonAdapter = FindAdapterOfMonitor(dxgiFactory, hMonSrc);
|
||||
|
||||
bool isSameAdapter = false;
|
||||
if (srcMonAdapter) {
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
HRESULT hr = srcMonAdapter->GetDesc(&desc);
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("IDXGIAdapter1::GetDesc 失败", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
const LUID renderAdapterLUID = device->GetAdapterLuid();
|
||||
|
||||
isSameAdapter = desc.AdapterLuid.HighPart == renderAdapterLUID.HighPart &&
|
||||
desc.AdapterLuid.LowPart == renderAdapterLUID.LowPart;
|
||||
} else {
|
||||
// 找不到源窗口所在屏幕的适配器则使用渲染设备
|
||||
srcMonAdapter.copy_from(dxgiAdapter);
|
||||
isSameAdapter = true;
|
||||
}
|
||||
|
||||
if (!_CreateD3D11Device(dxgiAdapter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
winrt::com_ptr<IDXGIDevice> dxgiDevice;
|
||||
HRESULT hr = _d3d11Device->QueryInterface<IDXGIDevice>(dxgiDevice.put());
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("获取 IDXGIDevice 失败", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = CreateDirect3D11DeviceFromDXGIDevice(
|
||||
dxgiDevice.get(),
|
||||
reinterpret_cast<::IInspectable**>(winrt::put_abi(_wrappedD3DDevice))
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("CreateDirect3D11DeviceFromDXGIDevice 失败", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
winrt::com_ptr<IGraphicsCaptureItemInterop> interop =
|
||||
winrt::try_get_activation_factory<winrt::GraphicsCaptureItem, IGraphicsCaptureItemInterop>();
|
||||
if (!interop) {
|
||||
Logger::Get().Error("获取 IGraphicsCaptureItemInterop 失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
const SrcTracker& srcTracker = ScalingWindow::Get().SrcTracker();
|
||||
const HWND hwndSrc = srcTracker.Handle();
|
||||
const RECT& srcRect = srcTracker.SrcRect();
|
||||
|
||||
RECT frameBounds;
|
||||
if (!CalcWindowCapturedFrameBounds(hwndSrc, frameBounds)) {
|
||||
Logger::Get().Error("CalcWindowCapturedFrameBounds 失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (srcRect.left < frameBounds.left || srcRect.top < frameBounds.top) {
|
||||
Logger::Get().Error("裁剪边框错误");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 在源窗口存在 DPI 缩放时有时会有一像素的偏移(取决于窗口在屏幕上的位置)
|
||||
// 可能是 DwmGetWindowAttribute 的 bug
|
||||
_frameBox = {
|
||||
UINT(srcRect.left - frameBounds.left),
|
||||
UINT(srcRect.top - frameBounds.top),
|
||||
0,
|
||||
UINT(srcRect.right - frameBounds.left),
|
||||
UINT(srcRect.bottom - frameBounds.top),
|
||||
1
|
||||
};
|
||||
|
||||
hr = interop->CreateForWindow(
|
||||
ScalingWindow::Get().SrcTracker().Handle(),
|
||||
winrt::guid_of<winrt::GraphicsCaptureItem>(),
|
||||
winrt::put_abi(_captureItem)
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("IGraphicsCaptureItemInterop::CreateForWindow 失败", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t frameCount = ScalingWindow::Get().Options().maxProducerFramesInFlight;
|
||||
_framesInUse.reserve(frameCount);
|
||||
for (uint32_t i = 0; i < frameCount; ++i) {
|
||||
_framesInUse.emplace_back(nullptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GraphicsCaptureFrameSource2::Start() noexcept {
|
||||
if (_captureSession) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建帧缓冲池。帧的尺寸和 _captureItem.Size() 不同
|
||||
_captureFramePool = winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(
|
||||
_wrappedD3DDevice,
|
||||
winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized,
|
||||
ScalingWindow::Get().Options().maxProducerFramesInFlight + 3,
|
||||
{ (int)_frameBox.right, (int)_frameBox.bottom } // 帧的尺寸为包含源窗口的最小尺寸
|
||||
);
|
||||
|
||||
_captureFramePool.FrameArrived([&](const winrt::Direct3D11CaptureFramePool& pool, const winrt::IInspectable&) {
|
||||
winrt::Direct3D11CaptureFrame frame = pool.TryGetNextFrame();
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 取最新帧
|
||||
while (true) {
|
||||
if (winrt::Direct3D11CaptureFrame nextFrame = pool.TryGetNextFrame()) {
|
||||
frame = std::move(nextFrame);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto lk = _lastestFrameLock.lock_exclusive();
|
||||
_lastestFrame = std::move(frame);
|
||||
});
|
||||
|
||||
_captureSession = _captureFramePool.CreateCaptureSession(_captureItem);
|
||||
|
||||
// 禁止捕获光标。从 Win10 v2004 开始支持
|
||||
if (winrt::ApiInformation::IsPropertyPresent(
|
||||
winrt::name_of<winrt::GraphicsCaptureSession>(),
|
||||
L"IsCursorCaptureEnabled"
|
||||
)) {
|
||||
_captureSession.IsCursorCaptureEnabled(false);
|
||||
}
|
||||
|
||||
// 不显示黄色边框,Win32 应用中无需请求权限。从 Win11 开始支持
|
||||
if (winrt::ApiInformation::IsPropertyPresent(
|
||||
winrt::name_of<winrt::GraphicsCaptureSession>(),
|
||||
L"IsBorderRequired"
|
||||
)) {
|
||||
_captureSession.IsBorderRequired(false);
|
||||
}
|
||||
|
||||
// Win11 24H2 中必须设置 MinUpdateInterval 才能使捕获帧率超过 60FPS
|
||||
if (winrt::ApiInformation::IsPropertyPresent(
|
||||
winrt::name_of<winrt::GraphicsCaptureSession>(),
|
||||
L"MinUpdateInterval"
|
||||
)) {
|
||||
_captureSession.MinUpdateInterval(1ms);
|
||||
}
|
||||
|
||||
_captureSession.StartCapture();
|
||||
} catch (const winrt::hresult_error& e) {
|
||||
Logger::Get().Info(StrHelper::Concat("Graphics Capture 失败: ", StrHelper::UTF16ToUTF8(e.message())));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FrameSourceState GraphicsCaptureFrameSource2::Update(uint32_t frameIndex) noexcept {
|
||||
auto lk = _lastestFrameLock.lock_exclusive();
|
||||
if (!_lastestFrame) {
|
||||
return FrameSourceState::Waiting;
|
||||
}
|
||||
|
||||
_framesInUse[frameIndex] = std::move(_lastestFrame);
|
||||
_lastestFrame = nullptr;
|
||||
|
||||
return FrameSourceState::NewFrame;
|
||||
}
|
||||
|
||||
static bool IsDebugLayersAvailable() noexcept {
|
||||
#ifdef _DEBUG
|
||||
static bool result = SUCCEEDED(D3D11CreateDevice(
|
||||
nullptr,
|
||||
D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device.
|
||||
nullptr,
|
||||
D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers.
|
||||
nullptr, // Any feature level will do.
|
||||
0,
|
||||
D3D11_SDK_VERSION,
|
||||
nullptr, // No need to keep the D3D device reference.
|
||||
nullptr, // No need to know the feature level.
|
||||
nullptr // No need to keep the D3D device context reference.
|
||||
));
|
||||
return result;
|
||||
#else
|
||||
// Relaese 配置不使用调试层
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GraphicsCaptureFrameSource2::_CreateD3D11Device(IDXGIAdapter1* dxgiAdapter) noexcept {
|
||||
D3D_FEATURE_LEVEL featureLevels[] = {
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0
|
||||
};
|
||||
const UINT nFeatureLevels = ARRAYSIZE(featureLevels);
|
||||
|
||||
UINT createDeviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
if (IsDebugLayersAvailable()) {
|
||||
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID3D11Device> d3dDevice;
|
||||
winrt::com_ptr<ID3D11DeviceContext> d3dDC;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
HRESULT hr = D3D11CreateDevice(
|
||||
dxgiAdapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
nullptr,
|
||||
createDeviceFlags,
|
||||
featureLevels,
|
||||
nFeatureLevels,
|
||||
D3D11_SDK_VERSION,
|
||||
d3dDevice.put(),
|
||||
&featureLevel,
|
||||
d3dDC.put()
|
||||
);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
Logger::Get().ComError("D3D11CreateDevice 失败", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string_view fl;
|
||||
switch (featureLevel) {
|
||||
case D3D_FEATURE_LEVEL_11_1:
|
||||
fl = "11.1";
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
fl = "11.0";
|
||||
break;
|
||||
default:
|
||||
fl = "未知";
|
||||
break;
|
||||
}
|
||||
Logger::Get().Info(fmt::format("已创建 D3D11 设备\n\t功能级别: {}", fl));
|
||||
|
||||
_d3d11Device = d3dDevice.try_as<ID3D11Device5>();
|
||||
if (!_d3d11Device) {
|
||||
Logger::Get().Error("获取 ID3D11Device5 失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
_d3d11DC = d3dDC.try_as<ID3D11DeviceContext4>();
|
||||
if (!_d3d11DC) {
|
||||
Logger::Get().Error("获取 ID3D11DeviceContext4 失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GraphicsCaptureFrameSource2::_StopCapture() noexcept {
|
||||
if (_captureSession) {
|
||||
_captureSession.Close();
|
||||
_captureSession = nullptr;
|
||||
}
|
||||
if (_captureFramePool) {
|
||||
_captureFramePool.Close();
|
||||
_captureFramePool = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
#include <Windows.Graphics.Capture.Interop.h>
|
||||
#include <winrt/Windows.Graphics.Capture.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
||||
|
|
@ -11,6 +13,7 @@ enum class FrameSourceState {
|
|||
class GraphicsCaptureFrameSource2 {
|
||||
public:
|
||||
GraphicsCaptureFrameSource2() = default;
|
||||
~GraphicsCaptureFrameSource2();
|
||||
|
||||
// 不可复制,不可移动
|
||||
GraphicsCaptureFrameSource2(const GraphicsCaptureFrameSource2&) = delete;
|
||||
|
|
@ -19,11 +22,41 @@ public:
|
|||
bool Initialize(
|
||||
ID3D12Device5* device,
|
||||
ID3D12CommandList* commandList,
|
||||
IDXGIFactory7* dxgiFactory,
|
||||
IDXGIAdapter4* dxgiAdapter,
|
||||
HMONITOR hMonSrc,
|
||||
bool useScRGB
|
||||
) noexcept;
|
||||
|
||||
FrameSourceState Update() noexcept;
|
||||
bool Start() noexcept;
|
||||
|
||||
FrameSourceState Update(uint32_t frameIndex) noexcept;
|
||||
|
||||
ID3D12Resource* GetOutput() noexcept {
|
||||
return _output.get();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _CreateD3D11Device(IDXGIAdapter1* dxgiAdapter) noexcept;
|
||||
|
||||
void _StopCapture() noexcept;
|
||||
|
||||
winrt::com_ptr<ID3D11Device5> _d3d11Device;
|
||||
winrt::com_ptr<ID3D11DeviceContext4> _d3d11DC;
|
||||
|
||||
winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice _wrappedD3DDevice{ nullptr };
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem _captureItem{ nullptr };
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureSession _captureSession{ nullptr };
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool _captureFramePool{ nullptr };
|
||||
|
||||
wil::srwlock _lastestFrameLock;
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame _lastestFrame{ nullptr };
|
||||
|
||||
std::vector<winrt::Windows::Graphics::Capture::Direct3D11CaptureFrame> _framesInUse;
|
||||
|
||||
winrt::com_ptr<ID3D12Resource> _output;
|
||||
|
||||
D3D11_BOX _frameBox{};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
#include "SwapChainPresenter.h"
|
||||
#include <d3dkmthk.h>
|
||||
#include <dispatcherqueue.h>
|
||||
#ifdef _DEBUG
|
||||
#include <dxgidebug.h>
|
||||
#endif
|
||||
#include <windows.graphics.display.interop.h>
|
||||
|
||||
namespace Magpie {
|
||||
|
|
@ -150,6 +152,8 @@ ScalingError Renderer2::Initialize(HWND hwndAttach, OverlayOptions& /*overlayOpt
|
|||
}
|
||||
}
|
||||
|
||||
_isProducerInitialized.wait(false, std::memory_order_acquire);
|
||||
|
||||
return ScalingError::NoError;
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +240,7 @@ bool Renderer2::Render(bool /*force*/, bool /*waitForGpu*/, bool onHandlingDevic
|
|||
|
||||
// 存在黑边时应填充背景。使用交换链呈现时需要这个操作,因为我们指定了
|
||||
// DXGI_SWAP_EFFECT_FLIP_DISCARD,同时也是为了和 RTSS 兼容。
|
||||
static constexpr FLOAT BLACK[4] = { 0.0f,0.0f,0.0f,1.0f };
|
||||
static constexpr FLOAT BLACK[4] = { 1.0f,0.0f,0.0f,1.0f };
|
||||
_consumerCommandList->ClearRenderTargetView(rtvHandle, BLACK, 0, nullptr);
|
||||
|
||||
if (bufferState == D3D12_RESOURCE_STATE_COPY_SOURCE) {
|
||||
|
|
@ -468,7 +472,7 @@ bool Renderer2::_TryCreateD3DDevice(const winrt::com_ptr<IDXGIAdapter1>& adapter
|
|||
flStr = "未知";
|
||||
break;
|
||||
}
|
||||
Logger::Get().Info(fmt::format("已创建 D3D 设备\n\t功能级别: {}", flStr));
|
||||
Logger::Get().Info(fmt::format("已创建 D3D12 设备\n\t功能级别: {}", flStr));
|
||||
} else {
|
||||
Logger::Get().ComError("CheckFeatureSupport 失败", hr);
|
||||
}
|
||||
|
|
@ -661,6 +665,7 @@ void Renderer2::_ProducerThreadProc() noexcept {
|
|||
while (true) {
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
_frameSource.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -737,11 +742,12 @@ bool Renderer2::_InitProducer() noexcept {
|
|||
}
|
||||
|
||||
_frameSource = std::make_unique<GraphicsCaptureFrameSource2>();
|
||||
if (!_frameSource->Initialize(_device.get(), _producerCommandList.get(), NULL, false)) {
|
||||
if (!_frameSource->Initialize(_device.get(), _producerCommandList.get(),
|
||||
_dxgiFactory.get(), _dxgiAdapter.get(), ScalingWindow::Get().SrcTracker().Monitor(), false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_destRect = ScalingWindow::Get().RendererRect();
|
||||
_destRect = ScalingWindow::Get().SrcTracker().SrcRect();
|
||||
|
||||
_producerCommandAllocators.resize(maxFramesInFlight);
|
||||
for (winrt::com_ptr<ID3D12CommandAllocator>& commandAllocator : _producerCommandAllocators) {
|
||||
|
|
@ -807,6 +813,15 @@ bool Renderer2::_InitProducer() noexcept {
|
|||
}
|
||||
}
|
||||
|
||||
// 最后启动捕获以尽可能推迟显示黄色边框 (Win10) 或禁用圆角 (Win11)
|
||||
if (!_frameSource->Start()) {
|
||||
Logger::Get().Error("启动捕获失败");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_isProducerInitialized.store(true, std::memory_order_release);
|
||||
_isProducerInitialized.notify_one();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -828,12 +843,12 @@ bool Renderer2::_ProducerRender() noexcept {
|
|||
curFrameBuffer.state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
HRESULT hr = _producerCommandAllocators[_curProducerCommandAllocatorIndex]->Reset();
|
||||
HRESULT hr = _producerCommandAllocators[_curProducerFrameIndex]->Reset();
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = _producerCommandList->Reset(_producerCommandAllocators[_curProducerCommandAllocatorIndex].get(), nullptr);
|
||||
hr = _producerCommandList->Reset(_producerCommandAllocators[_curProducerFrameIndex].get(), nullptr);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -856,9 +871,6 @@ bool Renderer2::_ProducerRender() noexcept {
|
|||
_producerCommandQueue->ExecuteCommandLists(1, &t);
|
||||
}
|
||||
|
||||
_curProducerCommandAllocatorIndex =
|
||||
(_curProducerCommandAllocatorIndex + 1) % (uint32_t)_producerCommandAllocators.size();
|
||||
|
||||
{
|
||||
auto lk = _frameBufferLock.lock_exclusive();
|
||||
|
||||
|
|
@ -868,9 +880,10 @@ bool Renderer2::_ProducerRender() noexcept {
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t nextProduceIndex = (_curProduceIndex + 1) % _frameBuffers.size();
|
||||
const uint32_t frameBufferCount = (uint32_t)_frameBuffers.size();
|
||||
const uint32_t nextProduceIndex = (_curProduceIndex + 1) % frameBufferCount;
|
||||
if (nextProduceIndex == _curConsumeIndex) {
|
||||
uint32_t nextConsumeIndex = (_curConsumeIndex + 1) % _frameBuffers.size();
|
||||
uint32_t nextConsumeIndex = (_curConsumeIndex + 1) % frameBufferCount;
|
||||
|
||||
uint64_t fenceValueToWait = _frameBuffers[nextConsumeIndex].producerFenceValue;
|
||||
if (_producerFrameBufferFence->GetCompletedValue() < fenceValueToWait) {
|
||||
|
|
@ -895,6 +908,9 @@ bool Renderer2::_ProducerRender() noexcept {
|
|||
uint64_t nextFenceValue = _frameBuffers[_curProduceIndex].producerFenceValue + 1;
|
||||
_curProduceIndex = nextProduceIndex;
|
||||
_frameBuffers[nextProduceIndex].producerFenceValue = nextFenceValue;
|
||||
|
||||
_curProducerFrameIndex =
|
||||
(_curProducerFrameIndex + 1) % (uint32_t)_producerCommandAllocators.size();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ private:
|
|||
winrt::com_ptr<ID3D12CommandQueue> _producerCommandQueue;
|
||||
winrt::com_ptr<ID3D12GraphicsCommandList> _producerCommandList;
|
||||
std::vector<winrt::com_ptr<ID3D12CommandAllocator>> _producerCommandAllocators;
|
||||
uint32_t _curProducerCommandAllocatorIndex = 0;
|
||||
uint32_t _curProducerFrameIndex = 0;
|
||||
|
||||
wil::srwlock _frameBufferLock;
|
||||
|
||||
|
|
@ -137,6 +137,7 @@ private:
|
|||
|
||||
bool _isFP16Supported = false;
|
||||
bool _isUsingWarp = false;
|
||||
std::atomic<bool> _isProducerInitialized = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -923,6 +923,7 @@ LRESULT ScalingWindow::_MessageHandler(UINT msg, WPARAM wParam, LPARAM lParam) n
|
|||
Logger::Get().Info("CursorManager 已析构");
|
||||
|
||||
_renderer.reset();
|
||||
_renderer2.reset();
|
||||
Logger::Get().Info("Renderer 已析构");
|
||||
|
||||
if (!_isSrcRepositioning) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue