Skip to content

Commit 6bf10c6

Browse files
committed
Usage of unused render states for special game scenarios
- use unused RenderState 42 to assign a remix texture category for the next surface - use unused RenderState 150 to set a custom material hash for the next surface - add hidden remix option 'useUnusedRenderstates' (default: false) to enable usage of unused render states
1 parent 912a164 commit 6bf10c6

5 files changed

Lines changed: 49 additions & 24 deletions

File tree

src/d3d9/d3d9_rtx.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,11 @@ namespace dxvk {
651651
// Hash material data
652652
m_activeDrawCallState.materialData.updateCachedHash();
653653

654+
// Custom hash set via unused D3D RenderState
655+
if (m_activeDrawCallState.materialData.remixHashFromD3D) {
656+
m_activeDrawCallState.materialData.setHashOverride(m_activeDrawCallState.materialData.remixHashFromD3D);
657+
}
658+
654659
// For shader based drawcalls we also want to capture the vertex shader output
655660
const bool needVertexCapture = m_parent->UseProgrammableVS() && useVertexCapture();
656661
if (needVertexCapture) {

src/d3d9/d3d9_rtx_utils.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ namespace dxvk {
176176

177177
materialData.alphaBlendEnabled = d3d9State.renderStates[D3DRS_ALPHABLENDENABLE] != FALSE;
178178

179+
if (RtxOptions::Get()->useUnusedRenderstates()) {
180+
materialData.remixTextureCategoryFlagsFromD3D = d3d9State.renderStates[42] != 0xfefefefe ? d3d9State.renderStates[42] : 0u; // D3DRENDERSTATETYPE index 42 is not in use - unused values are set to 0xfefefefe
181+
materialData.remixHashFromD3D = d3d9State.renderStates[150] != 0xfefefefe ? d3d9State.renderStates[150] : 0u; // D3DRENDERSTATETYPE index 150 is not in use - unused values are set to 0xfefefefe
182+
}
183+
179184
if (materialData.alphaBlendEnabled) {
180185
D3D9BlendState color;
181186
color.Src = D3DBLEND(d3d9State.renderStates[D3DRS_SRCBLEND]);

src/dxvk/rtx_render/rtx_materials.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,8 @@ struct LegacyMaterialData {
14511451
uint32_t tFactor = 0xffffffff; // Value for D3DRS_TEXTUREFACTOR, default value of is opaque white
14521452
D3DMATERIAL9 d3dMaterial = {};
14531453
bool isTextureFactorBlend = false;
1454+
uint32_t remixTextureCategoryFlagsFromD3D = 0;
1455+
uint32_t remixHashFromD3D = 0;
14541456

14551457
void setHashOverride(XXH64_hash_t hash) {
14561458
m_cachedHash = hash;

src/dxvk/rtx_render/rtx_options.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,9 @@ namespace dxvk {
989989
RTX_OPTION("rtx", float, effectLightRadius, 5.f, "");
990990
RTX_OPTION("rtx", bool, effectLightPlasmaBall, false, "");
991991

992+
RTX_OPTION("rtx", bool, useUnusedRenderstates, false, "Enable usage of unused D3D renderstates to aid with special game scenarios whilst having game code access.\n"
993+
"(RS 42) Setting the remix texture category for the next surface. (RS 150) Setting a user defined material hash for the next surface.");
994+
992995
RTX_OPTION("rtx", bool, useObsoleteHashOnTextureUpload, false,
993996
"Whether or not to use slower XXH64 hash on texture upload.\n"
994997
"New projects should not enable this option as this solely exists for compatibility with older hashing schemes.");

src/dxvk/rtx_render/rtx_types.cpp

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,39 +128,46 @@ namespace dxvk {
128128
}
129129
}
130130

131+
static bool wasCategorySetViaD3D(InstanceCategories category, uint32_t categoryFlags) {
132+
return categoryFlags & (1 << static_cast<uint32_t>(category));
133+
}
134+
131135
void DrawCallState::setupCategoriesForTexture() {
132136
// TODO (REMIX-231): It would probably be much more efficient to use a map of texture hash to category flags, rather
133137
// than doing N lookups per texture hash for each category.
134138
const XXH64_hash_t& textureHash = materialData.getColorTexture().getImageHash();
135139

136-
setCategory(InstanceCategories::WorldUI, lookupHash(RtxOptions::worldSpaceUiTextures(), textureHash));
137-
setCategory(InstanceCategories::WorldMatte, lookupHash(RtxOptions::worldSpaceUiBackgroundTextures(), textureHash));
140+
const auto& d3dCategoryEnabled = RtxOptions::Get()->useUnusedRenderstates();
141+
const auto& d3dCategoryFlag = materialData.remixTextureCategoryFlagsFromD3D;
138142

139-
setCategory(InstanceCategories::Ignore, lookupHash(RtxOptions::ignoreTextures(), textureHash));
140-
setCategory(InstanceCategories::IgnoreLights, lookupHash(RtxOptions::ignoreLights(), textureHash));
141-
setCategory(InstanceCategories::IgnoreAntiCulling, lookupHash(RtxOptions::antiCullingTextures(), textureHash));
142-
setCategory(InstanceCategories::IgnoreMotionBlur, lookupHash(RtxOptions::motionBlurMaskOutTextures(), textureHash));
143-
setCategory(InstanceCategories::IgnoreOpacityMicromap, lookupHash(RtxOptions::opacityMicromapIgnoreTextures(), textureHash) || isUsingRaytracedRenderTarget);
144-
setCategory(InstanceCategories::IgnoreAlphaChannel, lookupHash(RtxOptions::ignoreAlphaOnTextures(), textureHash));
145-
setCategory(InstanceCategories::IgnoreBakedLighting, lookupHash(RtxOptions::ignoreBakedLightingTextures(), textureHash));
143+
setCategory(InstanceCategories::WorldUI, lookupHash(RtxOptions::worldSpaceUiTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::WorldUI, d3dCategoryFlag)));
144+
setCategory(InstanceCategories::WorldMatte, lookupHash(RtxOptions::worldSpaceUiBackgroundTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::WorldMatte, d3dCategoryFlag)));
146145

147-
setCategory(InstanceCategories::Hidden, lookupHash(RtxOptions::hideInstanceTextures(), textureHash));
146+
setCategory(InstanceCategories::Ignore, lookupHash(RtxOptions::ignoreTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::Ignore, d3dCategoryFlag)));
147+
setCategory(InstanceCategories::IgnoreLights, lookupHash(RtxOptions::ignoreLights(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::IgnoreLights, d3dCategoryFlag)));
148+
setCategory(InstanceCategories::IgnoreAntiCulling, lookupHash(RtxOptions::antiCullingTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::IgnoreAntiCulling, d3dCategoryFlag)));
149+
setCategory(InstanceCategories::IgnoreMotionBlur, lookupHash(RtxOptions::motionBlurMaskOutTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::IgnoreMotionBlur, d3dCategoryFlag)));
150+
setCategory(InstanceCategories::IgnoreOpacityMicromap, lookupHash(RtxOptions::opacityMicromapIgnoreTextures(), textureHash) || isUsingRaytracedRenderTarget || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::IgnoreOpacityMicromap, d3dCategoryFlag)));
151+
setCategory(InstanceCategories::IgnoreAlphaChannel, lookupHash(RtxOptions::ignoreAlphaOnTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::IgnoreAlphaChannel, d3dCategoryFlag)));
152+
setCategory(InstanceCategories::IgnoreBakedLighting, lookupHash(RtxOptions::ignoreBakedLightingTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::IgnoreBakedLighting, d3dCategoryFlag)));
148153

149-
setCategory(InstanceCategories::Particle, lookupHash(RtxOptions::particleTextures(), textureHash));
150-
setCategory(InstanceCategories::Beam, lookupHash(RtxOptions::beamTextures(), textureHash));
154+
setCategory(InstanceCategories::Hidden, lookupHash(RtxOptions::hideInstanceTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::Hidden, d3dCategoryFlag)));
151155

152-
setCategory(InstanceCategories::DecalStatic, lookupHash(RtxOptions::decalTextures(), textureHash));
153-
setCategory(InstanceCategories::DecalDynamic, lookupHash(RtxOptions::dynamicDecalTextures(), textureHash));
154-
setCategory(InstanceCategories::DecalSingleOffset, lookupHash(RtxOptions::singleOffsetDecalTextures(), textureHash));
155-
setCategory(InstanceCategories::DecalNoOffset, lookupHash(RtxOptions::nonOffsetDecalTextures(), textureHash));
156+
setCategory(InstanceCategories::Particle, lookupHash(RtxOptions::particleTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::Particle, d3dCategoryFlag)));
157+
setCategory(InstanceCategories::Beam, lookupHash(RtxOptions::beamTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::Beam, d3dCategoryFlag)));
156158

157-
setCategory(InstanceCategories::AnimatedWater, lookupHash(RtxOptions::animatedWaterTextures(), textureHash));
159+
setCategory(InstanceCategories::DecalStatic, lookupHash(RtxOptions::decalTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::DecalStatic, d3dCategoryFlag)));
160+
setCategory(InstanceCategories::DecalDynamic, lookupHash(RtxOptions::dynamicDecalTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::DecalDynamic, d3dCategoryFlag)));
161+
setCategory(InstanceCategories::DecalSingleOffset, lookupHash(RtxOptions::singleOffsetDecalTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::DecalSingleOffset, d3dCategoryFlag)));
162+
setCategory(InstanceCategories::DecalNoOffset, lookupHash(RtxOptions::nonOffsetDecalTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::DecalNoOffset, d3dCategoryFlag)));
158163

159-
setCategory(InstanceCategories::ThirdPersonPlayerModel, lookupHash(RtxOptions::playerModelTextures(), textureHash));
160-
setCategory(InstanceCategories::ThirdPersonPlayerBody, lookupHash(RtxOptions::playerModelBodyTextures(), textureHash));
164+
setCategory(InstanceCategories::AnimatedWater, lookupHash(RtxOptions::animatedWaterTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::AnimatedWater, d3dCategoryFlag)));
161165

162-
setCategory(InstanceCategories::Terrain, lookupHash(RtxOptions::terrainTextures(), textureHash));
163-
setCategory(InstanceCategories::Sky, lookupHash(RtxOptions::skyBoxTextures(), textureHash));
166+
setCategory(InstanceCategories::ThirdPersonPlayerModel, lookupHash(RtxOptions::playerModelTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::ThirdPersonPlayerModel, d3dCategoryFlag)));
167+
setCategory(InstanceCategories::ThirdPersonPlayerBody, lookupHash(RtxOptions::playerModelBodyTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::ThirdPersonPlayerBody, d3dCategoryFlag)));
168+
169+
setCategory(InstanceCategories::Terrain, lookupHash(RtxOptions::terrainTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::Terrain, d3dCategoryFlag)));
170+
setCategory(InstanceCategories::Sky, lookupHash(RtxOptions::skyBoxTextures(), textureHash) || (d3dCategoryEnabled & wasCategorySetViaD3D(InstanceCategories::Sky, d3dCategoryFlag)));
164171
}
165172

166173
void DrawCallState::setupCategoriesForGeometry() {
@@ -297,9 +304,12 @@ namespace dxvk {
297304
return true;
298305
}
299306

300-
// NOTE: we use color texture hash for sky detection, however the replacement is hashed with
301-
// the whole legacy material hash (which, as of 12/9/2022, equals to color texture hash). Adding a check just in case.
302-
assert(drawCallState.getMaterialData().getColorTexture().getImageHash() == drawCallState.getMaterialData().getHash() && "Texture or material hash method changed!");
307+
// NOTE: disable assert if material is using a custom hash that was set via an unused D3D RenderState
308+
if (!drawCallState.getMaterialData().remixHashFromD3D) {
309+
// NOTE: we use color texture hash for sky detection, however the replacement is hashed with
310+
// the whole legacy material hash (which, as of 12/9/2022, equals to color texture hash). Adding a check just in case.
311+
assert(drawCallState.getMaterialData().getColorTexture().getImageHash() == drawCallState.getMaterialData().getHash() && "Texture or material hash method changed!");
312+
}
303313

304314
if (drawCallState.getMaterialData().usesTexture()) {
305315
if (lookupHash(RtxOptions::skyBoxTextures(), drawCallState.getMaterialData().getHash())) {

0 commit comments

Comments
 (0)