mirror of
https://github.com/rt64/rt64.git
synced 2025-01-13 06:45:28 +00:00
NVIDIA Driver Workaround.
This commit is contained in:
parent
646bb813a5
commit
6de3939913
@ -18,7 +18,6 @@ namespace RT64 {
|
||||
j["resolution"] = cfg.resolution;
|
||||
j["displayBuffering"] = cfg.displayBuffering;
|
||||
j["antialiasing"] = cfg.antialiasing;
|
||||
j["hardwareResolve"] = cfg.hardwareResolve;
|
||||
j["resolutionMultiplier"] = cfg.resolutionMultiplier;
|
||||
j["downsampleMultiplier"] = cfg.downsampleMultiplier;
|
||||
j["filtering"] = cfg.filtering;
|
||||
@ -31,6 +30,7 @@ namespace RT64 {
|
||||
j["refreshRate"] = cfg.refreshRate;
|
||||
j["refreshRateTarget"] = cfg.refreshRateTarget;
|
||||
j["internalColorFormat"] = cfg.internalColorFormat;
|
||||
j["hardwareResolve"] = cfg.hardwareResolve;
|
||||
j["idleWorkActive"] = cfg.idleWorkActive;
|
||||
j["developerMode"] = cfg.developerMode;
|
||||
}
|
||||
@ -41,7 +41,6 @@ namespace RT64 {
|
||||
cfg.resolution = j.value("resolution", defaultCfg.resolution);
|
||||
cfg.displayBuffering = j.value("displayBuffering", defaultCfg.displayBuffering);
|
||||
cfg.antialiasing = j.value("antialiasing", defaultCfg.antialiasing);
|
||||
cfg.hardwareResolve = j.value("hardwareResolve", defaultCfg.hardwareResolve);
|
||||
cfg.resolutionMultiplier = j.value("resolutionMultiplier", defaultCfg.resolutionMultiplier);
|
||||
cfg.downsampleMultiplier = j.value("downsampleMultiplier", defaultCfg.downsampleMultiplier);
|
||||
cfg.filtering = j.value("filtering", defaultCfg.filtering);
|
||||
@ -54,6 +53,7 @@ namespace RT64 {
|
||||
cfg.refreshRate = j.value("refreshRate", defaultCfg.refreshRate);
|
||||
cfg.refreshRateTarget = j.value("refreshRateTarget", defaultCfg.refreshRateTarget);
|
||||
cfg.internalColorFormat = j.value("internalColorFormat", defaultCfg.internalColorFormat);
|
||||
cfg.hardwareResolve = j.value("hardwareResolve", defaultCfg.hardwareResolve);
|
||||
cfg.idleWorkActive = j.value("idleWorkActive", defaultCfg.idleWorkActive);
|
||||
cfg.developerMode = j.value("developerMode", defaultCfg.developerMode);
|
||||
}
|
||||
@ -72,7 +72,6 @@ namespace RT64 {
|
||||
resolution = Resolution::WindowIntegerScale;
|
||||
displayBuffering = DisplayBuffering::Double;
|
||||
antialiasing = Antialiasing::None;
|
||||
hardwareResolve = true;
|
||||
resolutionMultiplier = 2.0f;
|
||||
downsampleMultiplier = 1;
|
||||
filtering = Filtering::AntiAliasedPixelScaling;
|
||||
@ -85,6 +84,7 @@ namespace RT64 {
|
||||
refreshRate = RefreshRate::Original;
|
||||
refreshRateTarget = 60;
|
||||
internalColorFormat = InternalColorFormat::Automatic;
|
||||
hardwareResolve = HardwareResolve::Automatic;
|
||||
idleWorkActive = true;
|
||||
developerMode = false;
|
||||
}
|
||||
@ -100,6 +100,7 @@ namespace RT64 {
|
||||
clampEnum<Upscale2D>(upscale2D);
|
||||
clampEnum<RefreshRate>(refreshRate);
|
||||
clampEnum<InternalColorFormat>(internalColorFormat);
|
||||
clampEnum<HardwareResolve>(hardwareResolve);
|
||||
resolutionMultiplier = std::clamp<double>(resolutionMultiplier, 0.0f, ResolutionMultiplierLimit);
|
||||
downsampleMultiplier = std::clamp<int>(downsampleMultiplier, 1, ResolutionMultiplierLimit);
|
||||
aspectTarget = std::clamp<double>(aspectTarget, 0.1f, 100.0f);
|
||||
|
@ -76,11 +76,17 @@ namespace RT64 {
|
||||
OptionCount
|
||||
};
|
||||
|
||||
enum class HardwareResolve {
|
||||
Disabled,
|
||||
Enabled,
|
||||
Automatic,
|
||||
OptionCount
|
||||
};
|
||||
|
||||
GraphicsAPI graphicsAPI;
|
||||
Resolution resolution;
|
||||
DisplayBuffering displayBuffering;
|
||||
Antialiasing antialiasing;
|
||||
bool hardwareResolve;
|
||||
double resolutionMultiplier;
|
||||
int downsampleMultiplier;
|
||||
Filtering filtering;
|
||||
@ -93,6 +99,7 @@ namespace RT64 {
|
||||
RefreshRate refreshRate;
|
||||
int refreshRateTarget;
|
||||
InternalColorFormat internalColorFormat;
|
||||
HardwareResolve hardwareResolve;
|
||||
bool idleWorkActive;
|
||||
bool developerMode;
|
||||
|
||||
@ -153,6 +160,12 @@ namespace RT64 {
|
||||
{ UserConfiguration::InternalColorFormat::Automatic, "Automatic" }
|
||||
});
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(UserConfiguration::HardwareResolve, {
|
||||
{ UserConfiguration::HardwareResolve::Disabled, "Disabled" },
|
||||
{ UserConfiguration::HardwareResolve::Enabled, "Enabled" },
|
||||
{ UserConfiguration::HardwareResolve::Automatic, "Automatic" }
|
||||
});
|
||||
|
||||
struct ConfigurationJSON {
|
||||
static bool read(UserConfiguration &cfg, std::istream &stream);
|
||||
static bool write(const UserConfiguration &cfg, std::ostream &stream);
|
||||
|
@ -3232,6 +3232,13 @@ namespace RT64 {
|
||||
capabilities.sampleLocations = samplePositionsOption;
|
||||
description.name = win32::Utf16ToUtf8(adapterDesc.Description);
|
||||
description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory;
|
||||
description.vendor = RenderDeviceVendor(adapterDesc.VendorId);
|
||||
|
||||
LARGE_INTEGER adapterVersion = {};
|
||||
res = adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &adapterVersion);
|
||||
if (SUCCEEDED(res)) {
|
||||
description.driverVersion = adapterVersion.QuadPart;
|
||||
}
|
||||
|
||||
if (preferUserChoice) {
|
||||
break;
|
||||
|
@ -156,29 +156,63 @@ namespace RT64 {
|
||||
return SetupResult::GraphicsDeviceNotFound;
|
||||
}
|
||||
|
||||
// Detect if the application should use hardware resolve or not.
|
||||
bool usesHardwareResolve = (userConfig.hardwareResolve != UserConfiguration::HardwareResolve::Disabled);
|
||||
|
||||
// Driver workarounds.
|
||||
//
|
||||
// Wireframe artifacts have been reported when using a high-precision color format on RDNA3 GPUs in D3D12. The workaround is to switch to Vulkan if this is the case.
|
||||
bool isRDNA3 = device->getDescription().name.find("AMD Radeon RX 7") != std::string::npos;
|
||||
bool useHDRinD3D12 = (userConfig.graphicsAPI == UserConfiguration::GraphicsAPI::D3D12) && (userConfig.internalColorFormat == UserConfiguration::InternalColorFormat::Automatic) && device->getCapabilities().preferHDR;
|
||||
if (isRDNA3 && useHDRinD3D12) {
|
||||
device.reset();
|
||||
renderInterface.reset();
|
||||
renderInterface = CreateVulkanInterface();
|
||||
if (renderInterface == nullptr) {
|
||||
fprintf(stderr, "Unable to initialize graphics API.\n");
|
||||
return SetupResult::GraphicsAPINotFound;
|
||||
const RenderDeviceVendor deviceVendor = device->getDescription().vendor;
|
||||
const uint64_t driverVersion = device->getDescription().driverVersion;
|
||||
if (deviceVendor == RenderDeviceVendor::NVIDIA) {
|
||||
if (createdGraphicsAPI == UserConfiguration::GraphicsAPI::D3D12) {
|
||||
if (usesHardwareResolve) {
|
||||
// MSAA Resolve in D3D12 is broken since 565.90. During Resolve operations, the contents from unrelated graphics commands in a queue can leak to other commands
|
||||
// being run in a different queue even if the resources aren't shared at all. The workaround is to disable hardware resolve and use rasterization instead.
|
||||
const uint64_t BrokenNVIDIADriverD3D12 = 0x00200000000f19be; // 565.90
|
||||
const uint64_t FixedNVIDIADriverD3D12 = UINT64_MAX; // No driver is known to fix the issue at the moment.
|
||||
if ((driverVersion >= BrokenNVIDIADriverD3D12) && (driverVersion < FixedNVIDIADriverD3D12) && (userConfig.hardwareResolve == UserConfiguration::HardwareResolve::Automatic)) {
|
||||
usesHardwareResolve = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (deviceVendor == RenderDeviceVendor::AMD) {
|
||||
// Wireframe artifacts have been reported when using a high-precision color format on RDNA3 GPUs in D3D12. The workaround is to switch to Vulkan if this is the case.
|
||||
bool isRDNA3 = device->getDescription().name.find("AMD Radeon RX 7") != std::string::npos;
|
||||
bool useHDRinD3D12 = (userConfig.graphicsAPI == UserConfiguration::GraphicsAPI::D3D12) && (userConfig.internalColorFormat == UserConfiguration::InternalColorFormat::Automatic) && device->getCapabilities().preferHDR;
|
||||
if (isRDNA3 && useHDRinD3D12) {
|
||||
device.reset();
|
||||
renderInterface.reset();
|
||||
renderInterface = CreateVulkanInterface();
|
||||
if (renderInterface == nullptr) {
|
||||
fprintf(stderr, "Unable to initialize graphics API.\n");
|
||||
return SetupResult::GraphicsAPINotFound;
|
||||
}
|
||||
|
||||
createdGraphicsAPI = UserConfiguration::GraphicsAPI::Vulkan;
|
||||
createdGraphicsAPI = UserConfiguration::GraphicsAPI::Vulkan;
|
||||
|
||||
device = renderInterface->createDevice();
|
||||
if (device == nullptr) {
|
||||
fprintf(stderr, "Unable to find compatible graphics device.\n");
|
||||
return SetupResult::GraphicsDeviceNotFound;
|
||||
device = renderInterface->createDevice();
|
||||
if (device == nullptr) {
|
||||
fprintf(stderr, "Unable to find compatible graphics device.\n");
|
||||
return SetupResult::GraphicsDeviceNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Detect if the application should use HDR framebuffers or not.
|
||||
bool usesHDR;
|
||||
switch (userConfig.internalColorFormat) {
|
||||
case UserConfiguration::InternalColorFormat::High:
|
||||
usesHDR = true;
|
||||
break;
|
||||
case UserConfiguration::InternalColorFormat::Automatic:
|
||||
usesHDR = device->getCapabilities().preferHDR;
|
||||
break;
|
||||
case UserConfiguration::InternalColorFormat::Standard:
|
||||
default:
|
||||
usesHDR = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Call the init hook if one was attached.
|
||||
RenderHookInit *initHook = GetRenderHookInit();
|
||||
if (initHook != nullptr) {
|
||||
@ -201,21 +235,6 @@ namespace RT64 {
|
||||
// Create the swap chain with the buffer count specified from the configuration.
|
||||
const uint32_t bufferCount = (userConfig.displayBuffering == UserConfiguration::DisplayBuffering::Triple) ? 3 : 2;
|
||||
swapChain = presentGraphicsWorker->commandQueue->createSwapChain(appWindow->windowHandle, bufferCount, RenderFormat::B8G8R8A8_UNORM);
|
||||
|
||||
// Detect if the application should use HDR framebuffers or not.
|
||||
bool usesHDR;
|
||||
switch (userConfig.internalColorFormat) {
|
||||
case UserConfiguration::InternalColorFormat::High:
|
||||
usesHDR = true;
|
||||
break;
|
||||
case UserConfiguration::InternalColorFormat::Automatic:
|
||||
usesHDR = device->getCapabilities().preferHDR;
|
||||
break;
|
||||
case UserConfiguration::InternalColorFormat::Standard:
|
||||
default:
|
||||
usesHDR = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Before configuring multisampling, make sure the device actually supports it for the formats we'll use. If it doesn't, turn off antialiasing in the configuration.
|
||||
const RenderSampleCounts colorSampleCounts = device->getSampleCountsSupported(RenderTarget::colorBufferFormat(usesHDR));
|
||||
@ -227,7 +246,7 @@ namespace RT64 {
|
||||
|
||||
// Create the shader library.
|
||||
const RenderMultisampling multisampling = RasterShader::generateMultisamplingPattern(userConfig.msaaSampleCount(), device->getCapabilities().sampleLocations);
|
||||
shaderLibrary = std::make_unique<ShaderLibrary>(usesHDR, userConfig.hardwareResolve);
|
||||
shaderLibrary = std::make_unique<ShaderLibrary>(usesHDR, usesHardwareResolve);
|
||||
shaderLibrary->setupCommonShaders(renderInterface.get(), device.get());
|
||||
shaderLibrary->setupMultisamplingShaders(renderInterface.get(), device.get(), multisampling);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "rt64_state.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "im3d/im3d.h"
|
||||
#include "im3d/im3d_math.h"
|
||||
@ -2080,14 +2081,14 @@ namespace RT64 {
|
||||
ImGui::Text("You must restart the application for this change to be applied.");
|
||||
}
|
||||
|
||||
genConfigChanged = ImGui::Checkbox("Three-Point Filtering", &userConfig.threePointFiltering) || genConfigChanged;
|
||||
genConfigChanged = ImGui::Checkbox("High Performance State", &userConfig.idleWorkActive) || genConfigChanged;
|
||||
|
||||
if (ImGui::Checkbox("Hardware Resolve", &userConfig.hardwareResolve)) {
|
||||
if (ImGui::Combo("Hardware Resolve", reinterpret_cast<int *>(&userConfig.hardwareResolve), "Disabled\0Enabled\0Automatic\0")) {
|
||||
// Update shader library to automatically control all logic around hardware resolve.
|
||||
ext.shaderLibrary->usesHardwareResolve = userConfig.hardwareResolve;
|
||||
ext.shaderLibrary->usesHardwareResolve = (userConfig.hardwareResolve != UserConfiguration::HardwareResolve::Disabled);
|
||||
genConfigChanged = true;
|
||||
}
|
||||
|
||||
genConfigChanged = ImGui::Checkbox("Three-Point Filtering", &userConfig.threePointFiltering) || genConfigChanged;
|
||||
genConfigChanged = ImGui::Checkbox("High Performance State", &userConfig.idleWorkActive) || genConfigChanged;
|
||||
|
||||
// Emulator configuration.
|
||||
ImGui::NewLine();
|
||||
@ -2430,12 +2431,15 @@ namespace RT64 {
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
const RenderDeviceDescription &description = ext.device->getDescription();
|
||||
const RenderDeviceCapabilities &capabilities = ext.device->getCapabilities();
|
||||
ImGui::Text("Display Refresh Rate (OS): %d\n", ext.appWindow->getRefreshRate());
|
||||
if (capabilities.displayTiming) {
|
||||
ImGui::Text("Display Refresh Rate (RHI): %d\n", ext.swapChain->getRefreshRate());
|
||||
}
|
||||
|
||||
ImGui::Text("Vendor ID: 0x%08x", uint32_t(description.vendor));
|
||||
ImGui::Text("Driver Version: 0x%016" PRIx64, description.driverVersion);
|
||||
ImGui::Text("Raytracing: %d", capabilities.raytracing);
|
||||
ImGui::Text("Raytracing State Update: %d", capabilities.raytracingStateUpdate);
|
||||
ImGui::Text("Sample Locations: %d", capabilities.sampleLocations);
|
||||
|
@ -63,6 +63,13 @@ namespace RT64 {
|
||||
|
||||
// Enums.
|
||||
|
||||
enum class RenderDeviceVendor {
|
||||
UNKNOWN = 0x0,
|
||||
AMD = 0x1002,
|
||||
NVIDIA = 0x10DE,
|
||||
INTEL = 0x8086
|
||||
};
|
||||
|
||||
enum class RenderFormat {
|
||||
UNKNOWN,
|
||||
R32G32B32A32_TYPELESS,
|
||||
@ -1692,7 +1699,8 @@ namespace RT64 {
|
||||
|
||||
struct RenderDeviceDescription {
|
||||
std::string name = "Unknown";
|
||||
uint32_t driverVersion = 0;
|
||||
RenderDeviceVendor vendor = RenderDeviceVendor::UNKNOWN;
|
||||
uint64_t driverVersion = 0;
|
||||
uint64_t dedicatedVideoMemory = 0;
|
||||
};
|
||||
|
||||
|
@ -3389,6 +3389,7 @@ namespace RT64 {
|
||||
physicalDevice = physicalDevices[i];
|
||||
description.name = std::string(deviceProperties.deviceName);
|
||||
description.driverVersion = deviceProperties.driverVersion;
|
||||
description.vendor = RenderDeviceVendor(deviceProperties.vendorID);
|
||||
currentDeviceTypeScore = deviceTypeScore;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user