mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[idd] capture: add direct full-copy workaround
This commit is contained in:
@@ -63,6 +63,14 @@ Disable no GPU warning
|
|||||||
processing. It does not enable GPU acceleration or change the active
|
processing. It does not enable GPU acceleration or change the active
|
||||||
adapter.
|
adapter.
|
||||||
|
|
||||||
|
Force full direct frame copies
|
||||||
|
Works around GPU drivers that corrupt partial D3D12 copies into the shared
|
||||||
|
transport heap. When enabled, the GPU copies every direct frame in full;
|
||||||
|
readback/indirect transfers continue using partial damage copies. This can
|
||||||
|
substantially increase GPU and shared-memory bandwidth, so leave it
|
||||||
|
disabled unless you encounter corruption. Changing it requests a driver
|
||||||
|
reload.
|
||||||
|
|
||||||
Unlike mode-list edits, preference checkboxes are saved when clicked.
|
Unlike mode-list edits, preference checkboxes are saved when clicked.
|
||||||
|
|
||||||
Software processing
|
Software processing
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ quadraphonic
|
|||||||
Quadro
|
Quadro
|
||||||
queueing
|
queueing
|
||||||
radeon
|
radeon
|
||||||
|
readback
|
||||||
realtime
|
realtime
|
||||||
renderer
|
renderer
|
||||||
repo
|
repo
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "capture/CHardwareFrameProcessor.h"
|
#include "capture/CHardwareFrameProcessor.h"
|
||||||
|
|
||||||
|
#include "config/CSettings.h"
|
||||||
#include "capture/CFrameProcessorUtil.h"
|
#include "capture/CFrameProcessorUtil.h"
|
||||||
#include "transport/IFrameTransport.h"
|
#include "transport/IFrameTransport.h"
|
||||||
#include "CSRWLock.h"
|
#include "CSRWLock.h"
|
||||||
@@ -76,11 +78,15 @@ CHardwareFrameProcessor::CHardwareFrameProcessor(
|
|||||||
CSRWLock * pipelineLock, HANDLE terminateEvent, bool useCadence) :
|
CSRWLock * pipelineLock, HANDLE terminateEvent, bool useCadence) :
|
||||||
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
CFrameProcessor(transport, std::move(dx12), postProcessors,
|
||||||
pipelineLock, terminateEvent),
|
pipelineLock, terminateEvent),
|
||||||
m_useCadence(useCadence)
|
m_useCadence(useCadence),
|
||||||
|
m_forceFullDirectCopy(CSettings::ShouldForceFullDirectCopy())
|
||||||
{
|
{
|
||||||
m_candidateAvailableEvent.Attach(
|
m_candidateAvailableEvent.Attach(
|
||||||
CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
CreateEvent(nullptr, FALSE, FALSE, nullptr));
|
||||||
m_copySubmitEvent.Attach(CreateEvent(nullptr, TRUE, TRUE, nullptr));
|
m_copySubmitEvent.Attach(CreateEvent(nullptr, TRUE, TRUE, nullptr));
|
||||||
|
|
||||||
|
if (m_forceFullDirectCopy)
|
||||||
|
DEBUG_INFO("Forcing full copies to direct transport memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHardwareFrameProcessor::IsValid() const
|
bool CHardwareFrameProcessor::IsValid() const
|
||||||
@@ -668,12 +674,17 @@ bool CHardwareFrameProcessor::Publish(
|
|||||||
|
|
||||||
RECT copyDirtyRects[LG_MAX_DIRTY_RECTS * 2] = {};
|
RECT copyDirtyRects[LG_MAX_DIRTY_RECTS * 2] = {};
|
||||||
unsigned nbCopyDirtyRects = 0;
|
unsigned nbCopyDirtyRects = 0;
|
||||||
const bool fullCopy = CFrameProcessorUtil::BuildCopyDamage(
|
// Some GPUs corrupt fragmented writes to the external transport heap.
|
||||||
postProcessor, prepared.targets[i].fullCopy,
|
// An unmapped target is a direct D3D12 transport resource; readback
|
||||||
previousDirtyRects, nbPreviousDirtyRects,
|
// targets remain mapped and continue using normal damage copies.
|
||||||
candidate.dirtyRects, candidate.nbDirtyRects,
|
const bool fullCopy =
|
||||||
candidate.dstFormat.width, candidate.dstFormat.height,
|
(m_forceFullDirectCopy && !fbRes->GetMap()) ||
|
||||||
copyDirtyRects, &nbCopyDirtyRects);
|
CFrameProcessorUtil::BuildCopyDamage(
|
||||||
|
postProcessor, prepared.targets[i].fullCopy,
|
||||||
|
previousDirtyRects, nbPreviousDirtyRects,
|
||||||
|
candidate.dirtyRects, candidate.nbDirtyRects,
|
||||||
|
candidate.dstFormat.width, candidate.dstFormat.height,
|
||||||
|
copyDirtyRects, &nbCopyDirtyRects);
|
||||||
fbRes->SetTiming(
|
fbRes->SetTiming(
|
||||||
candidate.captureTime, candidate.postProcessStart, publishStart);
|
candidate.captureTime, candidate.postProcessStart, publishStart);
|
||||||
fbRes->SetCandidateIndex(candidateIndex);
|
fbRes->SetCandidateIndex(candidateIndex);
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ private:
|
|||||||
CSRWLock m_copySubmitLock;
|
CSRWLock m_copySubmitLock;
|
||||||
bool m_publishPending = false;
|
bool m_publishPending = false;
|
||||||
bool m_useCadence = true;
|
bool m_useCadence = true;
|
||||||
|
bool m_forceFullDirectCopy = false;
|
||||||
Wrappers::Event m_candidateAvailableEvent;
|
Wrappers::Event m_candidateAvailableEvent;
|
||||||
Wrappers::Event m_copySubmitEvent;
|
Wrappers::Event m_copySubmitEvent;
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,11 @@ class CSettings
|
|||||||
return ReadBoolValue(L"LogStatistics");
|
return ReadBoolValue(L"LogStatistics");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ShouldForceFullDirectCopy()
|
||||||
|
{
|
||||||
|
return ReadBoolValue(L"ForceFullDirectCopy");
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const wchar_t * RegistryKey()
|
static const wchar_t * RegistryKey()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ CConfigWindow::CConfigWindow() : m_scale(1)
|
|||||||
m_defaultRefresh = m_settings.getDefaultRefresh();
|
m_defaultRefresh = m_settings.getDefaultRefresh();
|
||||||
m_noGPU = m_settings.getNoGPU();
|
m_noGPU = m_settings.getNoGPU();
|
||||||
m_exclusive = m_settings.getExclusiveMonitor();
|
m_exclusive = m_settings.getExclusiveMonitor();
|
||||||
|
m_forceFullDirectCopy = m_settings.getForceFullDirectCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateWindowEx(0, MAKEINTATOM(s_atom), L"Looking Glass IDD Configuration",
|
if (!CreateWindowEx(0, MAKEINTATOM(s_atom), L"Looking Glass IDD Configuration",
|
||||||
@@ -94,6 +95,7 @@ void CConfigWindow::updateFont()
|
|||||||
*m_modeWidth, *m_modeHeight, *m_modeRefresh, *m_modeUpdate, *m_modeDelete, *m_modeReset,
|
*m_modeWidth, *m_modeHeight, *m_modeRefresh, *m_modeUpdate, *m_modeDelete, *m_modeReset,
|
||||||
*m_defRefreshLabel, *m_defRefresh, *m_defRefreshHz, *m_modeSave, *m_modeRevert,
|
*m_defRefreshLabel, *m_defRefresh, *m_defRefreshHz, *m_modeSave, *m_modeRevert,
|
||||||
*m_prefGroup, *m_prefNoGPU, *m_prefExclusive,
|
*m_prefGroup, *m_prefNoGPU, *m_prefExclusive,
|
||||||
|
*m_prefForceFullDirectCopy,
|
||||||
}))
|
}))
|
||||||
SendMessage(child, WM_SETFONT, (WPARAM)m_font.Get(), 1);
|
SendMessage(child, WM_SETFONT, (WPARAM)m_font.Get(), 1);
|
||||||
}
|
}
|
||||||
@@ -187,6 +189,8 @@ LRESULT CConfigWindow::onCreate()
|
|||||||
m_prefGroup.reset(new CGroupBox(L"Preferences", 0, m_hwnd));
|
m_prefGroup.reset(new CGroupBox(L"Preferences", 0, m_hwnd));
|
||||||
m_prefNoGPU.reset(new CCheckbox(L"Disable no GPU warning", 0, m_hwnd));
|
m_prefNoGPU.reset(new CCheckbox(L"Disable no GPU warning", 0, m_hwnd));
|
||||||
m_prefExclusive.reset(new CCheckbox(L"Make LG the only monitor", 0, m_hwnd));
|
m_prefExclusive.reset(new CCheckbox(L"Make LG the only monitor", 0, m_hwnd));
|
||||||
|
m_prefForceFullDirectCopy.reset(new CCheckbox(
|
||||||
|
L"Force full direct frame copies", 0, m_hwnd));
|
||||||
|
|
||||||
if (m_noGPU)
|
if (m_noGPU)
|
||||||
m_prefNoGPU->setChecked(*m_noGPU);
|
m_prefNoGPU->setChecked(*m_noGPU);
|
||||||
@@ -194,6 +198,9 @@ LRESULT CConfigWindow::onCreate()
|
|||||||
if (m_exclusive)
|
if (m_exclusive)
|
||||||
m_prefExclusive->setChecked(*m_exclusive);
|
m_prefExclusive->setChecked(*m_exclusive);
|
||||||
|
|
||||||
|
if (m_forceFullDirectCopy)
|
||||||
|
m_prefForceFullDirectCopy->setChecked(*m_forceFullDirectCopy);
|
||||||
|
|
||||||
LONG width, height;
|
LONG width, height;
|
||||||
getMinimumSize(width, height);
|
getMinimumSize(width, height);
|
||||||
SetWindowPos(m_hwnd, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
|
SetWindowPos(m_hwnd, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
|
||||||
@@ -233,9 +240,10 @@ LRESULT CConfigWindow::onResize(DWORD width, DWORD height)
|
|||||||
pos.pinBottomLeft(*m_modeSave, 20, 20, 132, 24);
|
pos.pinBottomLeft(*m_modeSave, 20, 20, 132, 24);
|
||||||
pos.pinBottomLeft(*m_modeRevert, 154, 20, 50, 24);
|
pos.pinBottomLeft(*m_modeRevert, 154, 20, 50, 24);
|
||||||
|
|
||||||
pos.pinTopLeft(*m_prefGroup, 224, 40, 200, 72);
|
pos.pinTopLeft(*m_prefGroup, 224, 40, 200, 92);
|
||||||
pos.pinTopLeft(*m_prefNoGPU, 236, 64, 176, 20);
|
pos.pinTopLeft(*m_prefNoGPU, 236, 64, 176, 20);
|
||||||
pos.pinTopLeft(*m_prefExclusive, 236, 84, 176, 20);
|
pos.pinTopLeft(*m_prefExclusive, 236, 84, 176, 20);
|
||||||
|
pos.pinTopLeft(*m_prefForceFullDirectCopy, 236, 104, 188, 20);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +352,22 @@ LRESULT CConfigWindow::onCommand(WORD id, WORD code, HWND hwnd)
|
|||||||
m_settings.setExclusiveMonitor(*m_exclusive);
|
m_settings.setExclusiveMonitor(*m_exclusive);
|
||||||
m_prefExclusive->setChecked(*m_exclusive);
|
m_prefExclusive->setChecked(*m_exclusive);
|
||||||
}
|
}
|
||||||
|
else if (m_prefForceFullDirectCopy &&
|
||||||
|
hwnd == *m_prefForceFullDirectCopy && code == BN_CLICKED &&
|
||||||
|
m_forceFullDirectCopy)
|
||||||
|
{
|
||||||
|
const bool value = !*m_forceFullDirectCopy;
|
||||||
|
const LSTATUS result = m_settings.setForceFullDirectCopy(value);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR_HR(result, "Failed to save ForceFullDirectCopy");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_forceFullDirectCopy = value;
|
||||||
|
m_prefForceFullDirectCopy->setChecked(value);
|
||||||
|
sendSettingChange();
|
||||||
|
}
|
||||||
else if (m_modeSave && hwnd == *m_modeSave && code == BN_CLICKED)
|
else if (m_modeSave && hwnd == *m_modeSave && code == BN_CLICKED)
|
||||||
{
|
{
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ class CConfigWindow : public CWindow
|
|||||||
std::unique_ptr<CGroupBox> m_prefGroup;
|
std::unique_ptr<CGroupBox> m_prefGroup;
|
||||||
std::unique_ptr<CCheckbox> m_prefNoGPU;
|
std::unique_ptr<CCheckbox> m_prefNoGPU;
|
||||||
std::unique_ptr<CCheckbox> m_prefExclusive;
|
std::unique_ptr<CCheckbox> m_prefExclusive;
|
||||||
|
std::unique_ptr<CCheckbox> m_prefForceFullDirectCopy;
|
||||||
|
|
||||||
std::function<void()> m_onDestroy;
|
std::function<void()> m_onDestroy;
|
||||||
std::function<void()> m_onSettingChange;
|
std::function<void()> m_onSettingChange;
|
||||||
@@ -75,6 +76,7 @@ class CConfigWindow : public CWindow
|
|||||||
std::optional<DWORD> m_defaultRefresh;
|
std::optional<DWORD> m_defaultRefresh;
|
||||||
std::optional<bool> m_noGPU;
|
std::optional<bool> m_noGPU;
|
||||||
std::optional<bool> m_exclusive;
|
std::optional<bool> m_exclusive;
|
||||||
|
std::optional<bool> m_forceFullDirectCopy;
|
||||||
|
|
||||||
void getMinimumSize(LONG &width, LONG &height);
|
void getMinimumSize(LONG &width, LONG &height);
|
||||||
void updateFont();
|
void updateFont();
|
||||||
|
|||||||
@@ -265,3 +265,28 @@ LSTATUS CRegistrySettings::setExclusiveMonitor(bool exclusive)
|
|||||||
DWORD dwValue = exclusive;
|
DWORD dwValue = exclusive;
|
||||||
return RegSetValueEx(hKey, L"ExclusiveMonitor", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
|
return RegSetValueEx(hKey, L"ExclusiveMonitor", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<bool> CRegistrySettings::getForceFullDirectCopy()
|
||||||
|
{
|
||||||
|
DWORD result, cbData = sizeof result;
|
||||||
|
|
||||||
|
LSTATUS status = RegGetValue(hKey, nullptr, L"ForceFullDirectCopy",
|
||||||
|
RRF_RT_REG_DWORD, nullptr, &result, &cbData);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case ERROR_SUCCESS:
|
||||||
|
return !!result;
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR_HR(status, "RegGetValue(ForceFullDirectCopy)");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LSTATUS CRegistrySettings::setForceFullDirectCopy(bool forceFullCopy)
|
||||||
|
{
|
||||||
|
DWORD dwValue = forceFullCopy;
|
||||||
|
return RegSetValueEx(hKey, L"ForceFullDirectCopy", 0, REG_DWORD,
|
||||||
|
(LPBYTE)&dwValue, sizeof(DWORD));
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,4 +56,7 @@ public:
|
|||||||
|
|
||||||
std::optional<bool> getExclusiveMonitor();
|
std::optional<bool> getExclusiveMonitor();
|
||||||
LSTATUS setExclusiveMonitor(bool exclusive);
|
LSTATUS setExclusiveMonitor(bool exclusive);
|
||||||
|
|
||||||
|
std::optional<bool> getForceFullDirectCopy();
|
||||||
|
LSTATUS setForceFullDirectCopy(bool forceFullCopy);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user