Skip to content

Commit

Permalink
Usage of unused render states for special game scenarios
Browse files Browse the repository at this point in the history
- 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

review changes
  • Loading branch information
xoxor4d committed Oct 29, 2024
1 parent 912a164 commit c344e99
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 3 deletions.
5 changes: 5 additions & 0 deletions src/d3d9/d3d9_rtx_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ namespace dxvk {

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

if (RtxOptions::Get()->useUnusedRenderstates()) {
materialData.remixTextureCategoryFlagsFromD3D = d3d9State.renderStates[42] != 0xfefefefe ? d3d9State.renderStates[42] : 0u; // D3DRENDERSTATETYPE index 42 is not in use - unused values are set to 0xfefefefe
materialData.remixHashFromD3D = d3d9State.renderStates[150] != 0xfefefefe ? d3d9State.renderStates[150] : 0u; // D3DRENDERSTATETYPE index 150 is not in use - unused values are set to 0xfefefefe
}

if (materialData.alphaBlendEnabled) {
D3D9BlendState color;
color.Src = D3DBLEND(d3d9State.renderStates[D3DRS_SRCBLEND]);
Expand Down
7 changes: 7 additions & 0 deletions src/dxvk/rtx_render/rtx_materials.h
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,8 @@ struct LegacyMaterialData {
uint32_t tFactor = 0xffffffff; // Value for D3DRS_TEXTUREFACTOR, default value of is opaque white
D3DMATERIAL9 d3dMaterial = {};
bool isTextureFactorBlend = false;
uint32_t remixTextureCategoryFlagsFromD3D = 0u;
XXH64_hash_t remixHashFromD3D = 0;

void setHashOverride(XXH64_hash_t hash) {
m_cachedHash = hash;
Expand All @@ -1469,6 +1471,11 @@ struct LegacyMaterialData {
// plain data hash used by the RtSurfaceMaterial for storage in map-like data structures, but rather
// one used to identify a material and compare to user-provided hashes.
m_cachedHash = colorTextures[0].getImageHash();

// Custom hash set via unused D3D RenderState
if (remixHashFromD3D) {
m_cachedHash = remixHashFromD3D;
}
}

const static uint32_t kMaxSupportedTextures = 2;
Expand Down
3 changes: 3 additions & 0 deletions src/dxvk/rtx_render/rtx_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,9 @@ namespace dxvk {
RTX_OPTION("rtx", float, effectLightRadius, 5.f, "");
RTX_OPTION("rtx", bool, effectLightPlasmaBall, false, "");

RTX_OPTION("rtx", bool, useUnusedRenderstates, false, "Enable usage of unused D3D renderstates to aid with special game scenarios whilst having game code access.\n"
"(RS 42) Setting the remix texture category for the next surface. (RS 150) Setting a user defined material hash for the next surface.");

RTX_OPTION("rtx", bool, useObsoleteHashOnTextureUpload, false,
"Whether or not to use slower XXH64 hash on texture upload.\n"
"New projects should not enable this option as this solely exists for compatibility with older hashing schemes.");
Expand Down
13 changes: 10 additions & 3 deletions src/dxvk/rtx_render/rtx_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ namespace dxvk {
// than doing N lookups per texture hash for each category.
const XXH64_hash_t& textureHash = materialData.getColorTexture().getImageHash();

if (RtxOptions::Get()->useUnusedRenderstates()) {
categories = CategoryFlags(materialData.remixTextureCategoryFlagsFromD3D);
}

setCategory(InstanceCategories::WorldUI, lookupHash(RtxOptions::worldSpaceUiTextures(), textureHash));
setCategory(InstanceCategories::WorldMatte, lookupHash(RtxOptions::worldSpaceUiBackgroundTextures(), textureHash));

Expand Down Expand Up @@ -297,9 +301,12 @@ namespace dxvk {
return true;
}

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

if (drawCallState.getMaterialData().usesTexture()) {
if (lookupHash(RtxOptions::skyBoxTextures(), drawCallState.getMaterialData().getHash())) {
Expand Down

0 comments on commit c344e99

Please sign in to comment.