Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #10090 from Pokechu22/d3d-isnan-replacement
Use custom isnan implementation to avoid HLSL optimizer issues
  • Loading branch information
lioncash committed Sep 8, 2021
2 parents 282fda1 + 52c8273 commit 5538e90
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 7 deletions.
18 changes: 18 additions & 0 deletions Source/Core/VideoCommon/ShaderGenCommon.cpp
Expand Up @@ -87,6 +87,24 @@ std::string GetDiskShaderCacheFileName(APIType api_type, const char* type, bool
return filename;
}

void WriteIsNanHeader(ShaderCode& out, APIType api_type)
{
if (api_type == APIType::D3D)
{
out.Write("bool dolphin_isnan(float f) {{\n"
" // Workaround for the HLSL compiler deciding that isnan can never be true and\n"
" // optimising away the call, even though the value can actually be NaN\n"
" // Just look for the bit pattern that indicates NaN instead\n"
" return (asint(f) & 0x7FFFFFFF) > 0x7F800000;\n"
"}}\n\n");
// If isfinite is needed, (asint(f) & 0x7F800000) != 0x7F800000 can be used
}
else
{
out.Write("#define dolphin_isnan(f) isnan(f)\n");
}
}

static void DefineOutputMember(ShaderCode& object, APIType api_type, std::string_view qualifier,
std::string_view type, std::string_view name, int var_index,
std::string_view semantic = {}, int semantic_index = -1)
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/VideoCommon/ShaderGenCommon.h
Expand Up @@ -176,6 +176,8 @@ union ShaderHostConfig
std::string GetDiskShaderCacheFileName(APIType api_type, const char* type, bool include_gameid,
bool include_host_config, bool include_api = true);

void WriteIsNanHeader(ShaderCode& out, APIType api_type);

void GenerateVSOutputMembers(ShaderCode& object, APIType api_type, u32 texgens,
const ShaderHostConfig& host_config, std::string_view qualifier);

Expand Down
7 changes: 4 additions & 3 deletions Source/Core/VideoCommon/UberShaderVertex.cpp
Expand Up @@ -50,6 +50,7 @@ ShaderCode GenVertexShader(APIType api_type, const ShaderHostConfig& host_config
out.Write("}};\n\n");

WriteUberShaderCommonHeader(out, api_type, host_config);
WriteIsNanHeader(out, api_type);
WriteLightingFunction(out);

if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
Expand Down Expand Up @@ -438,9 +439,9 @@ static void GenVertexShaderTexGens(APIType api_type, u32 num_texgen, ShaderCode&
// Convert NaNs to 1 - needed to fix eyelids in Shadow the Hedgehog during cutscenes
// See https://bugs.dolphin-emu.org/issues/11458
out.Write(" // Convert NaN to 1\n");
out.Write(" if (isnan(coord.x)) coord.x = 1.0;\n");
out.Write(" if (isnan(coord.y)) coord.y = 1.0;\n");
out.Write(" if (isnan(coord.z)) coord.z = 1.0;\n");
out.Write(" if (dolphin_isnan(coord.x)) coord.x = 1.0;\n");
out.Write(" if (dolphin_isnan(coord.y)) coord.y = 1.0;\n");
out.Write(" if (dolphin_isnan(coord.z)) coord.z = 1.0;\n");

out.Write(" // first transformation\n");
out.Write(" uint texgentype = {};\n", BitfieldExtract<&TexMtxInfo::texgentype>("texMtxInfo"));
Expand Down
10 changes: 6 additions & 4 deletions Source/Core/VideoCommon/VertexShaderGen.cpp
Expand Up @@ -96,7 +96,9 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho

out.Write("struct VS_OUTPUT {{\n");
GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, host_config, "");
out.Write("}};\n");
out.Write("}};\n\n");

WriteIsNanHeader(out, api_type);

if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
{
Expand Down Expand Up @@ -335,9 +337,9 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
// Convert NaNs to 1 - needed to fix eyelids in Shadow the Hedgehog during cutscenes
// See https://bugs.dolphin-emu.org/issues/11458
out.Write("// Convert NaN to 1\n");
out.Write("if (isnan(coord.x)) coord.x = 1.0;\n");
out.Write("if (isnan(coord.y)) coord.y = 1.0;\n");
out.Write("if (isnan(coord.z)) coord.z = 1.0;\n");
out.Write("if (dolphin_isnan(coord.x)) coord.x = 1.0;\n");
out.Write("if (dolphin_isnan(coord.y)) coord.y = 1.0;\n");
out.Write("if (dolphin_isnan(coord.z)) coord.z = 1.0;\n");

// first transformation
switch (texinfo.texgentype)
Expand Down

0 comments on commit 5538e90

Please sign in to comment.