[dxgi] Fix refresh rate filtering in FindClosestMatchingMode

We need to operate on the pre-filtered list, or otherwise we may run into
problems where not all refresh rates are supported for all display modes.
This commit is contained in:
Philip Rebohle 2021-12-15 21:54:37 +01:00
parent 55c4aba4d0
commit b53c3057e1
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
1 changed files with 40 additions and 32 deletions

View File

@ -527,31 +527,7 @@ namespace dxvk {
void DxgiOutput::FilterModesByDesc(
std::vector<DXGI_MODE_DESC1>& Modes,
const DXGI_MODE_DESC1& TargetMode) {
uint32_t minDiffResolution = 0;
uint32_t minDiffRefreshRate = 0;
if (TargetMode.Width) {
minDiffResolution = std::accumulate(
Modes.begin(), Modes.end(), std::numeric_limits<uint32_t>::max(),
[&TargetMode] (uint32_t current, const DXGI_MODE_DESC1& mode) {
uint32_t diff = std::abs(int32_t(TargetMode.Width - mode.Width))
+ std::abs(int32_t(TargetMode.Height - mode.Height));
return std::min(current, diff);
});
}
if (TargetMode.RefreshRate.Numerator && TargetMode.RefreshRate.Denominator) {
minDiffRefreshRate = std::accumulate(
Modes.begin(), Modes.end(), std::numeric_limits<uint64_t>::max(),
[&TargetMode] (uint64_t current, const DXGI_MODE_DESC1& mode) {
uint64_t rate = uint64_t(mode.RefreshRate.Numerator)
* uint64_t(TargetMode.RefreshRate.Denominator)
/ uint64_t(mode.RefreshRate.Denominator);
uint64_t diff = std::abs(int64_t(rate - uint64_t(TargetMode.RefreshRate.Numerator)));
return std::min(current, diff);
});
}
// Filter modes based on format properties
bool testScanlineOrder = false;
bool testScaling = false;
bool testFormat = false;
@ -577,21 +553,53 @@ namespace dxvk {
if (testFormat)
skipMode |= it->Format != TargetMode.Format;
if (TargetMode.Width) {
it = skipMode ? Modes.erase(it) : ++it;
}
// Filter by closest resolution
uint32_t minDiffResolution = 0;
if (TargetMode.Width) {
minDiffResolution = std::accumulate(
Modes.begin(), Modes.end(), std::numeric_limits<uint32_t>::max(),
[&TargetMode] (uint32_t current, const DXGI_MODE_DESC1& mode) {
uint32_t diff = std::abs(int32_t(TargetMode.Width - mode.Width))
+ std::abs(int32_t(TargetMode.Height - mode.Height));
return std::min(current, diff);
});
for (auto it = Modes.begin(); it != Modes.end(); ) {
uint32_t diff = std::abs(int32_t(TargetMode.Width - it->Width))
+ std::abs(int32_t(TargetMode.Height - it->Height));
skipMode |= diff != minDiffResolution;
}
if (TargetMode.RefreshRate.Numerator && TargetMode.RefreshRate.Denominator) {
bool skipMode = diff != minDiffResolution;
it = skipMode ? Modes.erase(it) : ++it;
}
}
// Filter by closest refresh rate
uint32_t minDiffRefreshRate = 0;
if (TargetMode.RefreshRate.Numerator && TargetMode.RefreshRate.Denominator) {
minDiffRefreshRate = std::accumulate(
Modes.begin(), Modes.end(), std::numeric_limits<uint64_t>::max(),
[&TargetMode] (uint64_t current, const DXGI_MODE_DESC1& mode) {
uint64_t rate = uint64_t(mode.RefreshRate.Numerator)
* uint64_t(TargetMode.RefreshRate.Denominator)
/ uint64_t(mode.RefreshRate.Denominator);
uint64_t diff = std::abs(int64_t(rate - uint64_t(TargetMode.RefreshRate.Numerator)));
return std::min(current, diff);
});
for (auto it = Modes.begin(); it != Modes.end(); ) {
uint64_t rate = uint64_t(it->RefreshRate.Numerator)
* uint64_t(TargetMode.RefreshRate.Denominator)
/ uint64_t(it->RefreshRate.Denominator);
uint64_t diff = std::abs(int64_t(rate - uint64_t(TargetMode.RefreshRate.Numerator)));
skipMode |= diff != minDiffRefreshRate;
}
it = skipMode ? Modes.erase(it) : ++it;
bool skipMode = diff != minDiffRefreshRate;
it = skipMode ? Modes.erase(it) : ++it;
}
}
}