diff --git a/Source/Core/VideoCommon/ShaderGenCommon.cpp b/Source/Core/VideoCommon/ShaderGenCommon.cpp index 53cf3edf61..c5cd3ef30d 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.cpp +++ b/Source/Core/VideoCommon/ShaderGenCommon.cpp @@ -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) diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index 2a1dcf1215..3c1e7f38f8 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -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); diff --git a/Source/Core/VideoCommon/UberShaderVertex.cpp b/Source/Core/VideoCommon/UberShaderVertex.cpp index 5b02b1f989..70b434b786 100644 --- a/Source/Core/VideoCommon/UberShaderVertex.cpp +++ b/Source/Core/VideoCommon/UberShaderVertex.cpp @@ -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) @@ -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")); diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 4e4121b564..25fb5a06c5 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -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) { @@ -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)