Fix shim log path, numeric settings and RGB9E5 range
- Build the default log path from the DLL's folder, now recorded even without d4r.ini, instead of copying the name into a MAX_PATH buffer that a folder path of 246+ characters overflowed; no log is opened when that folder is unknown - Fall back to the default when a numeric setting does not start with a decimal digit, so MarkerPollUs = -1 no longer polls every ~71 minutes; hex values such as 0x40 still parse - Decode RGB9E5 exponent 0 as c * 2^-24 instead of zero, and encode with the format's real maximum 65408 (511 * 2^7) and exponents from 0 - Choose the RGB9E5 exponent by the rounded channel (< 511.5), so a value such as 511.25 keeps the lower exponent instead of decoding as 512
This commit is contained in:
1 parent
c4954dc3c4
commit
c7f645d153
1 file changed
+16
-28
+16
-28
@@ -481,12 +481,12 @@ static void load_portable_config()
|
|||||||
return;
|
return;
|
||||||
std::wstring dir(module, length);
|
std::wstring dir(module, length);
|
||||||
dir.resize(dir.find_last_of(L"\\/"));
|
dir.resize(dir.find_last_of(L"\\/"));
|
||||||
|
g_portable.dir = dir; // also without d4r.ini: the default log goes here
|
||||||
std::string text;
|
std::string text;
|
||||||
if (!read_whole_file(dir + L"\\d4r.ini", text))
|
if (!read_whole_file(dir + L"\\d4r.ini", text))
|
||||||
return; // developer layout: the launcher's environment has everything
|
return; // developer layout: the launcher's environment has everything
|
||||||
const std::vector<IniEntry> ini = parse_ini(text);
|
const std::vector<IniEntry> ini = parse_ini(text);
|
||||||
g_portable.active = true;
|
g_portable.active = true;
|
||||||
g_portable.dir = dir;
|
|
||||||
g_portable.unixDir = unix_path(dir);
|
g_portable.unixDir = unix_path(dir);
|
||||||
if (g_portable.unixDir.empty())
|
if (g_portable.unixDir.empty())
|
||||||
g_portable.notes.push_back("cannot map the d4r folder to a Linux path (not running under Wine?)");
|
g_portable.notes.push_back("cannot map the d4r folder to a Linux path (not running under Wine?)");
|
||||||
@@ -607,14 +607,10 @@ static void log_open()
|
|||||||
ensure_portable_config();
|
ensure_portable_config();
|
||||||
wchar_t path[MAX_PATH] = {};
|
wchar_t path[MAX_PATH] = {};
|
||||||
DWORD length = GetEnvironmentVariableW(L"D4R_SHIM_LOG", path, MAX_PATH);
|
DWORD length = GetEnvironmentVariableW(L"D4R_SHIM_LOG", path, MAX_PATH);
|
||||||
if (length == 0 || length >= MAX_PATH)
|
if (length > 0 && length < MAX_PATH)
|
||||||
{
|
|
||||||
GetModuleFileNameW(g_selfModule, path, MAX_PATH);
|
|
||||||
wchar_t* slash = wcsrchr(path, L'\\');
|
|
||||||
if (slash != nullptr)
|
|
||||||
wcscpy(slash + 1, L"d4r_nvngx.log");
|
|
||||||
}
|
|
||||||
g_log = _wfopen(path, g_logFresh ? L"w" : L"a");
|
g_log = _wfopen(path, g_logFresh ? L"w" : L"a");
|
||||||
|
else if (!g_portable.dir.empty()) // no log when the DLL's folder is unknown
|
||||||
|
g_log = _wfopen((g_portable.dir + L"\\d4r_nvngx.log").c_str(), g_logFresh ? L"w" : L"a");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void logf(const char* format, ...)
|
static void logf(const char* format, ...)
|
||||||
@@ -648,8 +644,8 @@ static unsigned int env_uint(const char* name, unsigned int fallback)
|
|||||||
{
|
{
|
||||||
char value[64] = {};
|
char value[64] = {};
|
||||||
DWORD length = GetEnvironmentVariableA(name, value, sizeof(value));
|
DWORD length = GetEnvironmentVariableA(name, value, sizeof(value));
|
||||||
if (length == 0 || length >= sizeof(value))
|
if (length == 0 || length >= sizeof(value) || value[0] < '0' || value[0] > '9')
|
||||||
return fallback;
|
return fallback; // also signs and text: strtoul turns "-1" into 4294967295
|
||||||
return static_cast<unsigned int>(std::strtoul(value, nullptr, 0));
|
return static_cast<unsigned int>(std::strtoul(value, nullptr, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -948,11 +944,11 @@ static void convert_row_in(Plane plane, DXGI_FORMAT format, const uint8_t* sourc
|
|||||||
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
|
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
|
||||||
{
|
{
|
||||||
// Microsoft spec: c = (p >> offset) & 0x1FF, E = (p >> 27) & 0x1F,
|
// Microsoft spec: c = (p >> offset) & 0x1FF, E = (p >> 27) & 0x1F,
|
||||||
// v = c * 2^(E - 24). E == 0 means an exact zero.
|
// v = c * 2^(E - 24) for every E: there is no implicit leading bit.
|
||||||
uint32_t packed;
|
uint32_t packed;
|
||||||
std::memcpy(&packed, source + x * 4, 4);
|
std::memcpy(&packed, source + x * 4, 4);
|
||||||
uint32_t e = (packed >> 27) & 0x1Fu;
|
uint32_t e = (packed >> 27) & 0x1Fu;
|
||||||
float scale = (e == 0) ? 0.0f : std::ldexp(1.0f, (int)e - 24);
|
float scale = std::ldexp(1.0f, (int)e - 24);
|
||||||
rgba[0] = static_cast<float>((packed >> 0) & 0x1FFu) * scale;
|
rgba[0] = static_cast<float>((packed >> 0) & 0x1FFu) * scale;
|
||||||
rgba[1] = static_cast<float>((packed >> 9) & 0x1FFu) * scale;
|
rgba[1] = static_cast<float>((packed >> 9) & 0x1FFu) * scale;
|
||||||
rgba[2] = static_cast<float>((packed >> 18) & 0x1FFu) * scale;
|
rgba[2] = static_cast<float>((packed >> 18) & 0x1FFu) * scale;
|
||||||
@@ -1093,31 +1089,23 @@ static void convert_r11g11b10_row(const uint8_t* source, uint16_t* half, UINT wi
|
|||||||
// Microsoft spec: v = c * 2^(E - 24), c in [0, 511]. The exponent is chosen as
|
// Microsoft spec: v = c * 2^(E - 24), c in [0, 511]. The exponent is chosen as
|
||||||
// the smallest E such that all channels fit in 9 bits, then each channel is
|
// the smallest E such that all channels fit in 9 bits, then each channel is
|
||||||
// rounded to the nearest representable value (round-half-even, matching
|
// rounded to the nearest representable value (round-half-even, matching
|
||||||
// D3D's conversion semantics). Values above the format's max (65024.0) are
|
// D3D's conversion semantics). Values above the format's max (65408.0) are
|
||||||
// clamped, like D3D12 does.
|
// clamped, like D3D12 does.
|
||||||
static void rgbe_pack(const float rgba[4], uint8_t* destination)
|
static void rgbe_pack(const float rgba[4], uint8_t* destination)
|
||||||
{
|
{
|
||||||
const float MAX_VALUE = 65024.0f; // 511 * 2^(24 - 24)
|
const float MAX_VALUE = 65408.0f; // 511 * 2^(31 - 24)
|
||||||
float r = rgba[0] < 0.0f ? 0.0f : (rgba[0] > MAX_VALUE ? MAX_VALUE : rgba[0]);
|
float r = rgba[0] < 0.0f ? 0.0f : (rgba[0] > MAX_VALUE ? MAX_VALUE : rgba[0]);
|
||||||
float g = rgba[1] < 0.0f ? 0.0f : (rgba[1] > MAX_VALUE ? MAX_VALUE : rgba[1]);
|
float g = rgba[1] < 0.0f ? 0.0f : (rgba[1] > MAX_VALUE ? MAX_VALUE : rgba[1]);
|
||||||
float b = rgba[2] < 0.0f ? 0.0f : (rgba[2] > MAX_VALUE ? MAX_VALUE : rgba[2]);
|
float b = rgba[2] < 0.0f ? 0.0f : (rgba[2] > MAX_VALUE ? MAX_VALUE : rgba[2]);
|
||||||
|
|
||||||
float mx = fmaxf(fmaxf(r, g), b);
|
float mx = fmaxf(fmaxf(r, g), b);
|
||||||
int e;
|
// Smallest scale (i.e. smallest e) such that mx / scale rounds to at most 511. This puts
|
||||||
if (mx == 0.0f)
|
// the largest channel in the 9-bit range [256, 511] (lower only at e == 0,
|
||||||
|
// which also encodes zero), the maximum precision the format allows.
|
||||||
|
int e = 31;
|
||||||
|
for (int et = 0; et <= 31; ++et)
|
||||||
{
|
{
|
||||||
e = 0; // exponent 0 encodes an exact zero in this format
|
if (mx / std::ldexp(1.0f, et - 24) < 511.5f) { e = et; break; }
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Smallest scale (i.e. smallest e) such that mx / scale <= 511. This
|
|
||||||
// puts the largest channel in the normalized 9-bit range [256, 511],
|
|
||||||
// which gives every channel the maximum precision the format allows.
|
|
||||||
e = 31;
|
|
||||||
for (int et = 1; et <= 31; ++et)
|
|
||||||
{
|
|
||||||
if (mx / std::ldexp(1.0f, et - 24) <= 511.0f) { e = et; break; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const float scale = std::ldexp(1.0f, e - 24);
|
const float scale = std::ldexp(1.0f, e - 24);
|
||||||
const float inv = 1.0f / scale;
|
const float inv = 1.0f / scale;
|
||||||
|
|||||||
Reference in new issue
Block a user