Skip to content

Commit 8315062

Browse files
Merge branch 'fix-REMIX-5640' into 'main'
[REMIX-5640][REMIX-5647] fix preserved draw bugs: unrespected RtxOption changes, legacy material changes, and uncleared hasMaterialChanged flags See merge request lightspeedrtx/dxvk-remix-nv!2188
2 parents eee0588 + 0df8b3f commit 8315062

10 files changed

Lines changed: 278 additions & 55 deletions

File tree

src/dxvk/rtx_render/rtx_materials.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,121 @@
2323
#include "rtx_materials.h"
2424

2525
#include "rtx_options.h"
26+
#include "../util/util_struct_hash.h"
2627

2728
namespace dxvk {
2829

30+
XXH64_hash_t LegacyMaterialData::computeIdentityHash() const {
31+
// Only fields consumed by determineMaterialData(), mergeLegacyMaterial(), and
32+
// InstanceManager surface alpha/blend setup. D3DMATERIAL9 constants, color-source
33+
// intermediates, texture slots, and alphaTestEnabled are excluded.
34+
struct LegacyMaterialIdentityHashData {
35+
XXH64_hash_t colorTextureHash0;
36+
XXH64_hash_t colorTextureHash1;
37+
XXH64_hash_t samplerHash0;
38+
XXH64_hash_t samplerHash1;
39+
uint32_t alphaTestCompareOp;
40+
uint32_t tFactor;
41+
uint32_t blendEnableBlending;
42+
uint32_t blendColorSrcFactor;
43+
uint32_t blendColorDstFactor;
44+
uint32_t blendColorBlendOp;
45+
uint32_t blendAlphaSrcFactor;
46+
uint32_t blendAlphaDstFactor;
47+
uint32_t blendAlphaBlendOp;
48+
uint32_t blendWriteMask;
49+
uint8_t alphaTestReferenceValue;
50+
uint8_t textureColorArg1Source;
51+
uint8_t textureColorArg2Source;
52+
uint8_t textureColorOperation;
53+
uint8_t textureAlphaArg1Source;
54+
uint8_t textureAlphaArg2Source;
55+
uint8_t textureAlphaOperation;
56+
uint8_t isTextureFactorBlend;
57+
uint8_t isVertexColorBakedLighting;
58+
uint8_t padding[7];
59+
};
60+
61+
static_assert(hasNoImplicitPadding<LegacyMaterialIdentityHashData>(
62+
&LegacyMaterialIdentityHashData::colorTextureHash0,
63+
&LegacyMaterialIdentityHashData::colorTextureHash1,
64+
&LegacyMaterialIdentityHashData::samplerHash0,
65+
&LegacyMaterialIdentityHashData::samplerHash1,
66+
&LegacyMaterialIdentityHashData::alphaTestCompareOp,
67+
&LegacyMaterialIdentityHashData::tFactor,
68+
&LegacyMaterialIdentityHashData::blendEnableBlending,
69+
&LegacyMaterialIdentityHashData::blendColorSrcFactor,
70+
&LegacyMaterialIdentityHashData::blendColorDstFactor,
71+
&LegacyMaterialIdentityHashData::blendColorBlendOp,
72+
&LegacyMaterialIdentityHashData::blendAlphaSrcFactor,
73+
&LegacyMaterialIdentityHashData::blendAlphaDstFactor,
74+
&LegacyMaterialIdentityHashData::blendAlphaBlendOp,
75+
&LegacyMaterialIdentityHashData::blendWriteMask,
76+
&LegacyMaterialIdentityHashData::alphaTestReferenceValue,
77+
&LegacyMaterialIdentityHashData::textureColorArg1Source,
78+
&LegacyMaterialIdentityHashData::textureColorArg2Source,
79+
&LegacyMaterialIdentityHashData::textureColorOperation,
80+
&LegacyMaterialIdentityHashData::textureAlphaArg1Source,
81+
&LegacyMaterialIdentityHashData::textureAlphaArg2Source,
82+
&LegacyMaterialIdentityHashData::textureAlphaOperation,
83+
&LegacyMaterialIdentityHashData::isTextureFactorBlend,
84+
&LegacyMaterialIdentityHashData::isVertexColorBakedLighting,
85+
&LegacyMaterialIdentityHashData::padding),
86+
"LegacyMaterialIdentityHashData has padding bytes");
87+
88+
LegacyMaterialIdentityHashData data{};
89+
data.colorTextureHash0 = colorTextures[0].getImageHash();
90+
data.colorTextureHash1 = colorTextures[1].getImageHash();
91+
data.samplerHash0 = samplers[0].ptr() != nullptr ? samplers[0]->info().calculateHash() : kEmptyHash;
92+
data.samplerHash1 = samplers[1].ptr() != nullptr ? samplers[1]->info().calculateHash() : kEmptyHash;
93+
data.alphaTestCompareOp = static_cast<uint32_t>(alphaTestCompareOp);
94+
data.tFactor = tFactor;
95+
data.blendEnableBlending = static_cast<uint32_t>(blendMode.enableBlending);
96+
data.blendColorSrcFactor = static_cast<uint32_t>(blendMode.colorSrcFactor);
97+
data.blendColorDstFactor = static_cast<uint32_t>(blendMode.colorDstFactor);
98+
data.blendColorBlendOp = static_cast<uint32_t>(blendMode.colorBlendOp);
99+
data.blendAlphaSrcFactor = static_cast<uint32_t>(blendMode.alphaSrcFactor);
100+
data.blendAlphaDstFactor = static_cast<uint32_t>(blendMode.alphaDstFactor);
101+
data.blendAlphaBlendOp = static_cast<uint32_t>(blendMode.alphaBlendOp);
102+
data.blendWriteMask = static_cast<uint32_t>(blendMode.writeMask);
103+
data.alphaTestReferenceValue = alphaTestReferenceValue;
104+
data.textureColorArg1Source = static_cast<uint8_t>(textureColorArg1Source);
105+
data.textureColorArg2Source = static_cast<uint8_t>(textureColorArg2Source);
106+
data.textureColorOperation = static_cast<uint8_t>(textureColorOperation);
107+
data.textureAlphaArg1Source = static_cast<uint8_t>(textureAlphaArg1Source);
108+
data.textureAlphaArg2Source = static_cast<uint8_t>(textureAlphaArg2Source);
109+
data.textureAlphaOperation = static_cast<uint8_t>(textureAlphaOperation);
110+
data.isTextureFactorBlend = isTextureFactorBlend ? 1u : 0u;
111+
data.isVertexColorBakedLighting = isVertexColorBakedLighting ? 1u : 0u;
112+
113+
return hashStructByMemory(
114+
data,
115+
&LegacyMaterialIdentityHashData::colorTextureHash0,
116+
&LegacyMaterialIdentityHashData::colorTextureHash1,
117+
&LegacyMaterialIdentityHashData::samplerHash0,
118+
&LegacyMaterialIdentityHashData::samplerHash1,
119+
&LegacyMaterialIdentityHashData::alphaTestCompareOp,
120+
&LegacyMaterialIdentityHashData::tFactor,
121+
&LegacyMaterialIdentityHashData::blendEnableBlending,
122+
&LegacyMaterialIdentityHashData::blendColorSrcFactor,
123+
&LegacyMaterialIdentityHashData::blendColorDstFactor,
124+
&LegacyMaterialIdentityHashData::blendColorBlendOp,
125+
&LegacyMaterialIdentityHashData::blendAlphaSrcFactor,
126+
&LegacyMaterialIdentityHashData::blendAlphaDstFactor,
127+
&LegacyMaterialIdentityHashData::blendAlphaBlendOp,
128+
&LegacyMaterialIdentityHashData::blendWriteMask,
129+
&LegacyMaterialIdentityHashData::alphaTestReferenceValue,
130+
&LegacyMaterialIdentityHashData::textureColorArg1Source,
131+
&LegacyMaterialIdentityHashData::textureColorArg2Source,
132+
&LegacyMaterialIdentityHashData::textureColorOperation,
133+
&LegacyMaterialIdentityHashData::textureAlphaArg1Source,
134+
&LegacyMaterialIdentityHashData::textureAlphaArg2Source,
135+
&LegacyMaterialIdentityHashData::textureAlphaOperation,
136+
&LegacyMaterialIdentityHashData::isTextureFactorBlend,
137+
&LegacyMaterialIdentityHashData::isVertexColorBakedLighting,
138+
&LegacyMaterialIdentityHashData::padding);
139+
}
140+
29141
bool getEnableDiffuseLayerOverrideHack() {
30142
return TranslucentMaterialOptions::enableDiffuseLayerOverride();
31143
}

src/dxvk/rtx_render/rtx_materials.h

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -495,22 +495,57 @@ struct RtSurface {
495495

496496
struct LegacyMaterialDefaults {
497497
friend class ImGUI;
498-
RTX_OPTION("rtx.legacyMaterial", float, anisotropy, 0.f, "The default roughness anisotropy to use for non-replaced \"legacy\" materials. Should be in the range -1 to 1, where 0 is isotropic.");
499-
RTX_OPTION("rtx.legacyMaterial", float, emissiveIntensity, 0.f, "The default emissive intensity to use for non-replaced \"legacy\" materials.");
500-
RTX_OPTION("rtx.legacyMaterial", bool, useAlbedoTextureIfPresent, true, "A flag to determine if an \"albedo\" texture (a qualifying color texture) from the original application should be used if present on non-replaced \"legacy\" materials.");
501-
RTX_OPTION("rtx.legacyMaterial", Vector3, albedoConstant, Vector3(1.0f, 1.0f, 1.0f), "The default albedo constant to use for non-replaced \"legacy\" materials. Should be a color in sRGB colorspace with gamma encoding.");
502-
RTX_OPTION("rtx.legacyMaterial", float, opacityConstant, 1.f, "The default opacity constant to use for non-replaced \"legacy\" materials. Should be in the range 0 to 1.");
503-
RTX_OPTION_ENV("rtx.legacyMaterial", float, roughnessConstant, 0.7f, "DXVK_LEGACY_MATERIAL_DEFAULT_ROUGHNESS", "The default perceptual roughness constant to use for non-replaced \"legacy\" materials. Should be in the range 0 to 1.");
504-
RTX_OPTION("rtx.legacyMaterial", float, metallicConstant, 0.1f, "The default metallic constant to use for non-replaced \"legacy\" materials. Should be in the range 0 to 1.");
505-
RTX_OPTION("rtx.legacyMaterial", Vector3, emissiveColorConstant, Vector3(0.0f, 0.0f, 0.0f), "The default emissive color constant to use for non-replaced \"legacy\" materials. Should be a color in sRGB colorspace with gamma encoding.");
506-
RTX_OPTION("rtx.legacyMaterial", bool, enableEmissive, false, "A flag to determine if emission should be used on non-replaced \"legacy\" materials.");
507-
RTX_OPTION("rtx.legacyMaterial", bool, ignoreAlphaChannel, false, "A flag to determine if the albedo alpha channel should be ignored on non-replaced \"legacy\" materials.");
508-
RTX_OPTION("rtx.legacyMaterial", bool, enableThinFilm, false, "A flag to determine if a thin-film layer should be used on non-replaced \"legacy\" materials.");
509-
RTX_OPTION("rtx.legacyMaterial", bool, alphaIsThinFilmThickness, false, "A flag to determine if the alpha channel from the albedo source should be treated as thin film thickness on non-replaced \"legacy\" materials.");
498+
RTX_OPTION_ARGS("rtx.legacyMaterial", float, anisotropy, 0.f,
499+
"The default roughness anisotropy to use for non-replaced \"legacy\" materials. "
500+
"Should be in the range -1 to 1, where 0 is isotropic.",
501+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
502+
RTX_OPTION_ARGS("rtx.legacyMaterial", float, emissiveIntensity, 0.f,
503+
"The default emissive intensity to use for non-replaced \"legacy\" materials.",
504+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
505+
RTX_OPTION_ARGS("rtx.legacyMaterial", bool, useAlbedoTextureIfPresent, true,
506+
"A flag to determine if an \"albedo\" texture (a qualifying color texture) from the original application "
507+
"should be used if present on non-replaced \"legacy\" materials.",
508+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
509+
RTX_OPTION_ARGS("rtx.legacyMaterial", Vector3, albedoConstant, Vector3(1.0f, 1.0f, 1.0f),
510+
"The default albedo constant to use for non-replaced \"legacy\" materials. "
511+
"Should be a color in sRGB colorspace with gamma encoding.",
512+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
513+
RTX_OPTION_ARGS("rtx.legacyMaterial", float, opacityConstant, 1.f,
514+
"The default opacity constant to use for non-replaced \"legacy\" materials. "
515+
"Should be in the range 0 to 1.",
516+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
517+
RTX_OPTION_ARGS("rtx.legacyMaterial", float, roughnessConstant, 0.7f,
518+
"The default perceptual roughness constant to use for non-replaced \"legacy\" materials. "
519+
"Should be in the range 0 to 1.",
520+
args.environment = "DXVK_LEGACY_MATERIAL_DEFAULT_ROUGHNESS",
521+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
522+
RTX_OPTION_ARGS("rtx.legacyMaterial", float, metallicConstant, 0.1f,
523+
"The default metallic constant to use for non-replaced \"legacy\" materials. "
524+
"Should be in the range 0 to 1.",
525+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
526+
RTX_OPTION_ARGS("rtx.legacyMaterial", Vector3, emissiveColorConstant, Vector3(0.0f, 0.0f, 0.0f),
527+
"The default emissive color constant to use for non-replaced \"legacy\" materials. "
528+
"Should be a color in sRGB colorspace with gamma encoding.",
529+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
530+
RTX_OPTION_ARGS("rtx.legacyMaterial", bool, enableEmissive, false,
531+
"A flag to determine if emission should be used on non-replaced \"legacy\" materials.",
532+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
533+
RTX_OPTION_ARGS("rtx.legacyMaterial", bool, ignoreAlphaChannel, false,
534+
"A flag to determine if the albedo alpha channel should be ignored on non-replaced \"legacy\" materials.",
535+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
536+
RTX_OPTION_ARGS("rtx.legacyMaterial", bool, enableThinFilm, false,
537+
"A flag to determine if a thin-film layer should be used on non-replaced \"legacy\" materials.",
538+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
539+
RTX_OPTION_ARGS("rtx.legacyMaterial", bool, alphaIsThinFilmThickness, false,
540+
"A flag to determine if the alpha channel from the albedo source should be treated as thin film thickness "
541+
"on non-replaced \"legacy\" materials.",
542+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
510543
// Note: Should be something non-zero as 0 is an invalid thickness to have (even if this is just unused).
511-
RTX_OPTION("rtx.legacyMaterial", float, thinFilmThicknessConstant, 200.f,
512-
"The thickness (in nanometers) of the thin-film layer assuming it is enabled on non-replaced \"legacy\" materials.\n"
513-
"Should be any value larger than 0, typically within the wavelength of light, but must be less than or equal to OPAQUE_SURFACE_MATERIAL_THIN_FILM_MAX_THICKNESS (" STRINGIFY(OPAQUE_SURFACE_MATERIAL_THIN_FILM_MAX_THICKNESS) " nm).");
544+
RTX_OPTION_ARGS("rtx.legacyMaterial", float, thinFilmThicknessConstant, 200.f,
545+
"The thickness (in nanometers) of the thin-film layer assuming it is enabled on non-replaced \"legacy\" materials.\n"
546+
"Should be any value larger than 0, typically within the wavelength of light, but must be less than or equal to "
547+
"OPAQUE_SURFACE_MATERIAL_THIN_FILM_MAX_THICKNESS (" STRINGIFY(OPAQUE_SURFACE_MATERIAL_THIN_FILM_MAX_THICKNESS) " nm).",
548+
args.flags = RtxOptionFlags::InvalidatesDrawcallTranslation);
514549
};
515550

516551
// Surface Materials
@@ -1707,6 +1742,9 @@ struct LegacyMaterialData {
17071742
return m_cachedHash;
17081743
}
17091744

1745+
// Hash of legacy material inputs that affect dynamic-path material binding.
1746+
XXH64_hash_t computeIdentityHash() const;
1747+
17101748
const TextureRef& getColorTexture() const {
17111749
return colorTextures[0];
17121750
}

src/dxvk/rtx_render/rtx_option_constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace dxvk {
5050
NoSave = 0x1, // Runtime-only option - routed to Derived layer, never saved to config files
5151
NoReset = 0x2, // Don't reset this option when layer is cleared via UI
5252
UserSetting = 0x4, // End-user setting - belongs in User or Quality layers, not in mod configs
53+
InvalidatesDrawcallTranslation = 0x8, // Options that invalidate preserved draw calls (forces retranslation next frame when changed)
5354
};
5455

5556
// Mask of flags that determine which layer an option belongs in.

src/dxvk/rtx_render/rtx_option_manager.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828

2929
namespace dxvk {
3030

31+
// Indicates that an option with the InvalidatesDrawcallTranslation flag has been changed since the last frame.
32+
// This should only ever be modified or read on the dxvk-cs thread.
33+
bool RtxOptionManager::s_drawcallTranslationInvalid = false;
34+
3135
// ============================================================================
3236
// RtxOptionManager static method implementations
3337
// ============================================================================
@@ -185,6 +189,9 @@ namespace dxvk {
185189

186190
// Invoke onChange callbacks after promoting all values
187191
for (RtxOptionImpl* rtxOption : dirtyOptionsVector) {
192+
if ((rtxOption->getFlags() & RtxOptionFlags::InvalidatesDrawcallTranslation) != 0) {
193+
s_drawcallTranslationInvalid = true;
194+
}
188195
rtxOption->invokeOnChangeCallback(device);
189196
}
190197

@@ -211,6 +218,14 @@ namespace dxvk {
211218
getDirtyOptionMap().clear();
212219
}
213220

221+
void RtxOptionManager::clearDrawcallTranslationInvalid() {
222+
s_drawcallTranslationInvalid = false;
223+
}
224+
225+
bool RtxOptionManager::isDrawcallTranslationInvalid() {
226+
return s_drawcallTranslationInvalid;
227+
}
228+
214229
void RtxOptionManager::logEffectiveValues() {
215230
Logger::info("Effective RtxOption values (after all config layers and migrations):");
216231

src/dxvk/rtx_render/rtx_option_manager.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,16 @@ namespace dxvk {
125125
// A value is redundant if lower priority layers would resolve to the same value
126126
static size_t removeRedundantLayerValues(const RtxOptionLayer* layer);
127127

128+
// When an RtxOption that is used during draw call translation is changed, this flag is set to true.
129+
// This flag is cleared at the start of SceneManager::onFrameEnd before processing any dirty options.
130+
// Call this only from the dxvk-cs thread.
131+
static bool isDrawcallTranslationInvalid();
132+
// Call this only from the dxvk-cs thread.
133+
static void clearDrawcallTranslationInvalid();
134+
128135
private:
129136
static std::mutex s_layerMutex;
137+
static bool s_drawcallTranslationInvalid;
130138

131139
// Remove a layer from the registry and all options (internal use only)
132140
static bool unregisterLayer(const RtxOptionLayer* layer);

0 commit comments

Comments
 (0)