Workaround for Intel FrontFacing built-in variable bug (#2540)
This commit is contained in:
parent
0a80a837cb
commit
c3e2646f9e
13 changed files with 161 additions and 113 deletions
|
@ -157,15 +157,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
offsetExpr = Enclose(offsetExpr, src2, Instruction.ShiftRightS32, isLhs: true);
|
||||
|
||||
var config = context.Config;
|
||||
bool indexElement = !config.GpuAccessor.QueryHostHasVectorIndexingBug();
|
||||
|
||||
if (src1 is AstOperand oper && oper.Type == OperandType.Constant)
|
||||
{
|
||||
bool cbIndexable = context.Config.UsedFeatures.HasFlag(Translation.FeatureFlags.CbIndexing);
|
||||
return OperandManager.GetConstantBufferName(oper.Value, offsetExpr, context.Config.Stage, cbIndexable);
|
||||
bool cbIndexable = config.UsedFeatures.HasFlag(Translation.FeatureFlags.CbIndexing);
|
||||
return OperandManager.GetConstantBufferName(oper.Value, offsetExpr, config.Stage, cbIndexable, indexElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
string slotExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
|
||||
return OperandManager.GetConstantBufferName(slotExpr, offsetExpr, context.Config.Stage);
|
||||
return OperandManager.GetConstantBufferName(slotExpr, offsetExpr, config.Stage, indexElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,7 +317,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
// 2D Array and Cube shadow samplers with LOD level or bias requires an extension.
|
||||
// If the extension is not supported, just remove the LOD parameter.
|
||||
if (isArray && isShadow && (is2D || isCube) && !context.Config.GpuAccessor.QuerySupportsTextureShadowLod())
|
||||
if (isArray && isShadow && (is2D || isCube) && !context.Config.GpuAccessor.QueryHostSupportsTextureShadowLod())
|
||||
{
|
||||
hasLodBias = false;
|
||||
hasLodLevel = false;
|
||||
|
@ -322,7 +325,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
// Cube shadow samplers with LOD level requires an extension.
|
||||
// If the extension is not supported, just remove the LOD level parameter.
|
||||
if (isShadow && isCube && !context.Config.GpuAccessor.QuerySupportsTextureShadowLod())
|
||||
if (isShadow && isCube && !context.Config.GpuAccessor.QueryHostSupportsTextureShadowLod())
|
||||
{
|
||||
hasLodLevel = false;
|
||||
}
|
||||
|
|
|
@ -117,8 +117,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
return $"{GetUbName(stage, slot, cbIndexable)}[{offset >> 2}].{GetSwizzleMask(offset & 3)}";
|
||||
}
|
||||
|
||||
private static string GetVec4Indexed(string vectorName, string indexExpr)
|
||||
private static string GetVec4Indexed(string vectorName, string indexExpr, bool indexElement)
|
||||
{
|
||||
if (indexElement)
|
||||
{
|
||||
return $"{vectorName}[{indexExpr}]";
|
||||
}
|
||||
|
||||
string result = $"{vectorName}.x";
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
|
@ -127,14 +132,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
return $"({result})";
|
||||
}
|
||||
|
||||
public static string GetConstantBufferName(int slot, string offsetExpr, ShaderStage stage, bool cbIndexable)
|
||||
public static string GetConstantBufferName(int slot, string offsetExpr, ShaderStage stage, bool cbIndexable, bool indexElement)
|
||||
{
|
||||
return GetVec4Indexed(GetUbName(stage, slot, cbIndexable) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3");
|
||||
return GetVec4Indexed(GetUbName(stage, slot, cbIndexable) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
|
||||
}
|
||||
|
||||
public static string GetConstantBufferName(string slotExpr, string offsetExpr, ShaderStage stage)
|
||||
public static string GetConstantBufferName(string slotExpr, string offsetExpr, ShaderStage stage, bool indexElement)
|
||||
{
|
||||
return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3");
|
||||
return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
|
||||
}
|
||||
|
||||
public static string GetOutAttributeName(AstOperand attr, ShaderConfig config)
|
||||
|
@ -198,6 +203,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
case AttributeConsts.PositionY: return $"(gl_FragCoord.y / {DefaultNames.SupportBlockRenderScaleName}[0])";
|
||||
case AttributeConsts.PositionZ: return "gl_FragCoord.z";
|
||||
case AttributeConsts.PositionW: return "gl_FragCoord.w";
|
||||
|
||||
case AttributeConsts.FrontFacing:
|
||||
if (config.GpuAccessor.QueryHostHasFrontFacingBug())
|
||||
{
|
||||
// This is required for Intel on Windows, gl_FrontFacing sometimes returns incorrect
|
||||
// (flipped) values. Doing this seems to fix it.
|
||||
return "(-floatBitsToInt(float(gl_FrontFacing)) < 0)";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,36 @@
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool QueryHostHasFrontFacingBug()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryHostHasVectorIndexingBug()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int QueryHostStorageBufferOffsetAlignment()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
bool QueryHostSupportsImageLoadFormatted()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryHostSupportsNonConstantTextureOffset()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryHostSupportsTextureShadowLod()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryIsTextureBuffer(int handle, int cbufSlot = -1)
|
||||
{
|
||||
return false;
|
||||
|
@ -64,26 +94,6 @@
|
|||
return InputTopology.Points;
|
||||
}
|
||||
|
||||
int QueryStorageBufferOffsetAlignment()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
bool QuerySupportsImageLoadFormatted()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QuerySupportsNonConstantTextureOffset()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QuerySupportsTextureShadowLod()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TextureFormat QueryTextureFormat(int handle, int cbufSlot = -1)
|
||||
{
|
||||
return TextureFormat.R8G8B8A8Unorm;
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
|
||||
Operand baseAddrTrunc = Local();
|
||||
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryStorageBufferOffsetAlignment());
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
|
||||
|
||||
Operation andOp = new Operation(Instruction.BitwiseAnd, baseAddrTrunc, baseAddrLow, alignMask);
|
||||
|
||||
|
@ -142,7 +142,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
|
||||
Operand baseAddrTrunc = Local();
|
||||
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryStorageBufferOffsetAlignment());
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
|
||||
|
||||
Operation andOp = new Operation(Instruction.BitwiseAnd, baseAddrTrunc, baseAddrLow, alignMask);
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
sbSlot = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
|
||||
}
|
||||
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryStorageBufferOffsetAlignment());
|
||||
Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
|
||||
|
||||
Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
|
||||
Operand byteOffset = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
|
||||
|
@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
||||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
|
||||
bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.GpuAccessor.QuerySupportsNonConstantTextureOffset();
|
||||
bool hasInvalidOffset = (hasOffset || hasOffsets) && !config.GpuAccessor.QueryHostSupportsNonConstantTextureOffset();
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
{
|
||||
// When the formatted load extension is supported, we don't need to
|
||||
// specify a format, we can just declare it without a format and the GPU will handle it.
|
||||
if (GpuAccessor.QuerySupportsImageLoadFormatted())
|
||||
if (GpuAccessor.QueryHostSupportsImageLoadFormatted())
|
||||
{
|
||||
return TextureFormat.Unknown;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue