mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-22 09:03:36 +00:00
Geometry shader passthrough emulation
This commit is contained in:
parent
2713703d45
commit
dd54eb4be1
13 changed files with 93 additions and 53 deletions
|
@ -16,6 +16,7 @@ namespace Ryujinx.Graphics.GAL
|
||||||
public readonly bool SupportsR4G4Format;
|
public readonly bool SupportsR4G4Format;
|
||||||
public readonly bool SupportsFragmentShaderInterlock;
|
public readonly bool SupportsFragmentShaderInterlock;
|
||||||
public readonly bool SupportsFragmentShaderOrderingIntel;
|
public readonly bool SupportsFragmentShaderOrderingIntel;
|
||||||
|
public readonly bool SupportsGeometryShaderPassthrough;
|
||||||
public readonly bool SupportsImageLoadFormatted;
|
public readonly bool SupportsImageLoadFormatted;
|
||||||
public readonly bool SupportsMismatchingViewFormat;
|
public readonly bool SupportsMismatchingViewFormat;
|
||||||
public readonly bool SupportsNonConstantTextureOffset;
|
public readonly bool SupportsNonConstantTextureOffset;
|
||||||
|
@ -44,6 +45,7 @@ namespace Ryujinx.Graphics.GAL
|
||||||
bool supportsR4G4Format,
|
bool supportsR4G4Format,
|
||||||
bool supportsFragmentShaderInterlock,
|
bool supportsFragmentShaderInterlock,
|
||||||
bool supportsFragmentShaderOrderingIntel,
|
bool supportsFragmentShaderOrderingIntel,
|
||||||
|
bool supportsGeometryShaderPassthrough,
|
||||||
bool supportsImageLoadFormatted,
|
bool supportsImageLoadFormatted,
|
||||||
bool supportsMismatchingViewFormat,
|
bool supportsMismatchingViewFormat,
|
||||||
bool supportsNonConstantTextureOffset,
|
bool supportsNonConstantTextureOffset,
|
||||||
|
@ -69,6 +71,7 @@ namespace Ryujinx.Graphics.GAL
|
||||||
SupportsR4G4Format = supportsR4G4Format;
|
SupportsR4G4Format = supportsR4G4Format;
|
||||||
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
||||||
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||||
|
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
||||||
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
||||||
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
|
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
|
||||||
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
|
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 1;
|
private const uint CodeGenVersion = 2;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
|
|
@ -105,64 +105,37 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host about the presence of the FrontFacing built-in variable bug.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if the bug is present on the host device used, false otherwise</returns>
|
|
||||||
public bool QueryHostHasFrontFacingBug() => _context.Capabilities.HasFrontFacingBug;
|
public bool QueryHostHasFrontFacingBug() => _context.Capabilities.HasFrontFacingBug;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host about the presence of the vector indexing bug.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if the bug is present on the host device used, false otherwise</returns>
|
|
||||||
public bool QueryHostHasVectorIndexingBug() => _context.Capabilities.HasVectorIndexingBug;
|
public bool QueryHostHasVectorIndexingBug() => _context.Capabilities.HasVectorIndexingBug;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host storage buffer alignment required.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Host storage buffer alignment in bytes</returns>
|
|
||||||
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host support for texture formats with BGRA component order (such as BGRA8).
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if BGRA formats are supported, false otherwise</returns>
|
|
||||||
public bool QueryHostSupportsBgraFormat() => _context.Capabilities.SupportsBgraFormat;
|
public bool QueryHostSupportsBgraFormat() => _context.Capabilities.SupportsBgraFormat;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host support for fragment shader ordering critical sections on the shader code.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if fragment shader interlock is supported, false otherwise</returns>
|
|
||||||
public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
|
public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host support for fragment shader ordering scoped critical sections on the shader code.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if fragment shader ordering is supported, false otherwise</returns>
|
|
||||||
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host support for readable images without a explicit format declaration on the shader.
|
public bool QueryHostSupportsGeometryShaderPassthrough() => _context.Capabilities.SupportsGeometryShaderPassthrough;
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if formatted image load is supported, false otherwise</returns>
|
/// <inheritdoc/>
|
||||||
public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
|
public bool QueryHostSupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host GPU non-constant texture offset support.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if the GPU and driver supports non-constant texture offsets, false otherwise</returns>
|
|
||||||
public bool QueryHostSupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset;
|
public bool QueryHostSupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host GPU shader ballot support.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if the GPU and driver supports shader ballot, false otherwise</returns>
|
|
||||||
public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
|
public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot;
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Queries host GPU texture shadow LOD support.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True if the GPU and driver supports texture shadow LOD, false otherwise</returns>
|
|
||||||
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
|
public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
private static readonly Lazy<bool> _supportsDrawTexture = new Lazy<bool>(() => HasExtension("GL_NV_draw_texture"));
|
private static readonly Lazy<bool> _supportsDrawTexture = new Lazy<bool>(() => HasExtension("GL_NV_draw_texture"));
|
||||||
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
||||||
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
||||||
|
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new Lazy<bool>(() => HasExtension("GL_NV_geometry_shader_passthrough"));
|
||||||
private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
||||||
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
||||||
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
||||||
|
@ -47,6 +48,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
||||||
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
||||||
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
||||||
|
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
|
||||||
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
||||||
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||||
|
|
|
@ -110,6 +110,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
supportsR4G4Format: false,
|
supportsR4G4Format: false,
|
||||||
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
|
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
|
||||||
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
|
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
|
||||||
|
supportsGeometryShaderPassthrough: HwCapabilities.SupportsGeometryShaderPassthrough,
|
||||||
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
|
supportsImageLoadFormatted: HwCapabilities.SupportsImageLoadFormatted,
|
||||||
supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat,
|
supportsMismatchingViewFormat: HwCapabilities.SupportsMismatchingViewFormat,
|
||||||
supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset,
|
supportsNonConstantTextureOffset: HwCapabilities.SupportsNonConstantTextureOffset,
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
context.AppendLine("#extension GL_ARB_shader_viewport_layer_array : enable");
|
context.AppendLine("#extension GL_ARB_shader_viewport_layer_array : enable");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Config.GpPassthrough)
|
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable");
|
context.AppendLine("#extension GL_NV_geometry_shader_passthrough : enable");
|
||||||
}
|
}
|
||||||
|
@ -127,11 +127,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
{
|
{
|
||||||
if (context.Config.Stage == ShaderStage.Geometry)
|
if (context.Config.Stage == ShaderStage.Geometry)
|
||||||
{
|
{
|
||||||
string inPrimitive = context.Config.GpuAccessor.QueryPrimitiveTopology().ToGlslString();
|
InputTopology inputTopology = context.Config.GpuAccessor.QueryPrimitiveTopology();
|
||||||
|
string inPrimitive = inputTopology.ToGlslString();
|
||||||
|
|
||||||
context.AppendLine($"layout ({inPrimitive}) in;");
|
context.AppendLine($"layout ({inPrimitive}) in;");
|
||||||
|
|
||||||
if (context.Config.GpPassthrough)
|
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
context.AppendLine($"layout (passthrough) in gl_PerVertex");
|
context.AppendLine($"layout (passthrough) in gl_PerVertex");
|
||||||
context.EnterScope();
|
context.EnterScope();
|
||||||
|
@ -144,7 +145,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
{
|
{
|
||||||
string outPrimitive = context.Config.OutputTopology.ToGlslString();
|
string outPrimitive = context.Config.OutputTopology.ToGlslString();
|
||||||
|
|
||||||
int maxOutputVertices = context.Config.MaxOutputVertices;
|
int maxOutputVertices = context.Config.GpPassthrough
|
||||||
|
? inputTopology.ToInputVertices()
|
||||||
|
: context.Config.MaxOutputVertices;
|
||||||
|
|
||||||
context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
|
context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
|
||||||
}
|
}
|
||||||
|
@ -563,7 +566,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
string pass = (context.Config.PassthroughAttributes & (1 << attr)) != 0 ? "passthrough, " : string.Empty;
|
bool passthrough = (context.Config.PassthroughAttributes & (1 << attr)) != 0;
|
||||||
|
string pass = passthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough() ? "passthrough, " : string.Empty;
|
||||||
string name = $"{DefaultNames.IAttributePrefix}{attr}";
|
string name = $"{DefaultNames.IAttributePrefix}{attr}";
|
||||||
|
|
||||||
if (context.Config.TransformFeedbackEnabled && context.Config.Stage != ShaderStage.Vertex)
|
if (context.Config.TransformFeedbackEnabled && context.Config.Stage != ShaderStage.Vertex)
|
||||||
|
|
|
@ -425,7 +425,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
var spvType = context.TypePointer(StorageClass.Input, attrType);
|
var spvType = context.TypePointer(StorageClass.Input, attrType);
|
||||||
var spvVar = context.Variable(spvType, StorageClass.Input);
|
var spvVar = context.Variable(spvType, StorageClass.Input);
|
||||||
|
|
||||||
if (context.Config.PassthroughAttributes != 0)
|
if (context.Config.PassthroughAttributes != 0 && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
context.Decorate(spvVar, Decoration.PassthroughNV);
|
context.Decorate(spvVar, Decoration.PassthroughNV);
|
||||||
}
|
}
|
||||||
|
@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
{
|
{
|
||||||
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)context.InputVertices));
|
attrType = context.TypeArray(attrType, context.Constant(context.TypeU32(), (LiteralInteger)context.InputVertices));
|
||||||
|
|
||||||
if (context.Config.GpPassthrough)
|
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
builtInPassthrough = true;
|
builtInPassthrough = true;
|
||||||
}
|
}
|
||||||
|
@ -581,7 +581,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
|
|
||||||
if (!isOutAttr)
|
if (!isOutAttr)
|
||||||
{
|
{
|
||||||
if (!perPatch && (context.Config.PassthroughAttributes & (1 << location)) != 0)
|
if (!perPatch &&
|
||||||
|
(context.Config.PassthroughAttributes & (1 << location)) != 0 &&
|
||||||
|
context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
context.Decorate(spvVar, Decoration.PassthroughNV);
|
context.Decorate(spvVar, Decoration.PassthroughNV);
|
||||||
}
|
}
|
||||||
|
@ -646,7 +648,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((context.Config.PassthroughAttributes & (1 << location)) != 0)
|
if ((context.Config.PassthroughAttributes & (1 << location)) != 0 &&
|
||||||
|
context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
context.Decorate(spvVar, Decoration.PassthroughNV);
|
context.Decorate(spvVar, Decoration.PassthroughNV);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
{
|
{
|
||||||
context.AddCapability(Capability.Geometry);
|
context.AddCapability(Capability.Geometry);
|
||||||
|
|
||||||
if (config.GpPassthrough)
|
if (config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||||
{
|
{
|
||||||
context.AddExtension("SPV_NV_geometry_shader_passthrough");
|
context.AddExtension("SPV_NV_geometry_shader_passthrough");
|
||||||
context.AddCapability(Capability.GeometryShaderPassthroughNV);
|
context.AddCapability(Capability.GeometryShaderPassthroughNV);
|
||||||
|
@ -230,7 +230,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\".")
|
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\".")
|
||||||
});
|
});
|
||||||
|
|
||||||
context.AddExecutionMode(spvFunc, ExecutionMode.OutputVertices, (SpvLiteralInteger)context.Config.MaxOutputVertices);
|
int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices;
|
||||||
|
|
||||||
|
context.AddExecutionMode(spvFunc, ExecutionMode.OutputVertices, (SpvLiteralInteger)maxOutputVertices);
|
||||||
}
|
}
|
||||||
else if (context.Config.Stage == ShaderStage.Fragment)
|
else if (context.Config.Stage == ShaderStage.Fragment)
|
||||||
{
|
{
|
||||||
|
|
|
@ -197,6 +197,15 @@ namespace Ryujinx.Graphics.Shader
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries host GPU geometry shader passthrough support.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the GPU and driver supports geometry shader passthrough, false otherwise</returns>
|
||||||
|
bool QueryHostSupportsGeometryShaderPassthrough()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries host support for readable images without a explicit format declaration on the shader.
|
/// Queries host support for readable images without a explicit format declaration on the shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
|
|
||||||
AggregateType elemType;
|
AggregateType elemType;
|
||||||
|
|
||||||
if (!isOutAttr)
|
if (config.Stage == ShaderStage.Vertex && !isOutAttr)
|
||||||
{
|
{
|
||||||
elemType = config.GpuAccessor.QueryAttributeType(location) switch
|
elemType = config.GpuAccessor.QueryAttributeType(location) switch
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.Decoders;
|
||||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
@ -232,6 +233,44 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
PrepareForVertexReturn();
|
PrepareForVertexReturn();
|
||||||
}
|
}
|
||||||
|
else if (Config.Stage == ShaderStage.Geometry)
|
||||||
|
{
|
||||||
|
void WriteOutput(int index, int primIndex)
|
||||||
|
{
|
||||||
|
Operand x = this.LoadAttribute(Const(index), Const(0), Const(primIndex));
|
||||||
|
Operand y = this.LoadAttribute(Const(index + 4), Const(0), Const(primIndex));
|
||||||
|
Operand z = this.LoadAttribute(Const(index + 8), Const(0), Const(primIndex));
|
||||||
|
Operand w = this.LoadAttribute(Const(index + 12), Const(0), Const(primIndex));
|
||||||
|
|
||||||
|
this.Copy(Attribute(index), x);
|
||||||
|
this.Copy(Attribute(index + 4), y);
|
||||||
|
this.Copy(Attribute(index + 8), z);
|
||||||
|
this.Copy(Attribute(index + 12), w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.GpPassthrough)
|
||||||
|
{
|
||||||
|
int inputVertices = Config.GpuAccessor.QueryPrimitiveTopology().ToInputVertices();
|
||||||
|
|
||||||
|
for (int primIndex = 0; primIndex < inputVertices; primIndex++)
|
||||||
|
{
|
||||||
|
WriteOutput(AttributeConsts.PositionX, primIndex);
|
||||||
|
|
||||||
|
int passthroughAttributes = Config.PassthroughAttributes;
|
||||||
|
while (passthroughAttributes != 0)
|
||||||
|
{
|
||||||
|
int index = BitOperations.TrailingZeroCount(passthroughAttributes);
|
||||||
|
WriteOutput(AttributeConsts.UserAttributeBase + index * 16, primIndex);
|
||||||
|
Config.SetOutputUserAttribute(index, perPatch: false);
|
||||||
|
passthroughAttributes &= ~(1 << index);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.EmitVertex();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.EndPrimitive();
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (Config.Stage == ShaderStage.Fragment)
|
else if (Config.Stage == ShaderStage.Fragment)
|
||||||
{
|
{
|
||||||
bool supportsBgra = Config.GpuAccessor.QueryHostSupportsBgraFormat();
|
bool supportsBgra = Config.GpuAccessor.QueryHostSupportsBgraFormat();
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
public ShaderStage Stage { get; }
|
public ShaderStage Stage { get; }
|
||||||
|
|
||||||
public bool GpPassthrough { get; }
|
public bool GpPassthrough { get; }
|
||||||
|
public bool GpPassthroughWithHostSupport => GpPassthrough && GpuAccessor.QueryHostSupportsGeometryShaderPassthrough();
|
||||||
public bool LastInVertexPipeline { get; private set; }
|
public bool LastInVertexPipeline { get; private set; }
|
||||||
|
|
||||||
public int ThreadsPerInputPrimitive { get; }
|
public int ThreadsPerInputPrimitive { get; }
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
internal bool SupportsCustomBorderColor { get; private set; }
|
internal bool SupportsCustomBorderColor { get; private set; }
|
||||||
internal bool SupportsIndirectParameters { get; private set; }
|
internal bool SupportsIndirectParameters { get; private set; }
|
||||||
internal bool SupportsFragmentShaderInterlock { get; private set; }
|
internal bool SupportsFragmentShaderInterlock { get; private set; }
|
||||||
|
internal bool SupportsGeometryShaderPassthrough { get; private set; }
|
||||||
internal bool SupportsSubgroupSizeControl { get; private set; }
|
internal bool SupportsSubgroupSizeControl { get; private set; }
|
||||||
|
|
||||||
internal uint QueueFamilyIndex { get; private set; }
|
internal uint QueueFamilyIndex { get; private set; }
|
||||||
|
@ -123,6 +124,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
SupportsCustomBorderColor = supportedExtensions.Contains("VK_EXT_custom_border_color");
|
SupportsCustomBorderColor = supportedExtensions.Contains("VK_EXT_custom_border_color");
|
||||||
SupportsIndirectParameters = supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName);
|
SupportsIndirectParameters = supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName);
|
||||||
SupportsFragmentShaderInterlock = supportedExtensions.Contains("VK_EXT_fragment_shader_interlock");
|
SupportsFragmentShaderInterlock = supportedExtensions.Contains("VK_EXT_fragment_shader_interlock");
|
||||||
|
SupportsGeometryShaderPassthrough = supportedExtensions.Contains("VK_NV_geometry_shader_passthrough");
|
||||||
SupportsSubgroupSizeControl = supportedExtensions.Contains("VK_EXT_subgroup_size_control");
|
SupportsSubgroupSizeControl = supportedExtensions.Contains("VK_EXT_subgroup_size_control");
|
||||||
|
|
||||||
if (api.TryGetDeviceExtension(_instance, _device, out KhrSwapchain swapchainApi))
|
if (api.TryGetDeviceExtension(_instance, _device, out KhrSwapchain swapchainApi))
|
||||||
|
@ -311,6 +313,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
supportsR4G4Format: false,
|
supportsR4G4Format: false,
|
||||||
supportsFragmentShaderInterlock: SupportsFragmentShaderInterlock,
|
supportsFragmentShaderInterlock: SupportsFragmentShaderInterlock,
|
||||||
supportsFragmentShaderOrderingIntel: false,
|
supportsFragmentShaderOrderingIntel: false,
|
||||||
|
supportsGeometryShaderPassthrough: SupportsGeometryShaderPassthrough,
|
||||||
supportsImageLoadFormatted: features.ShaderStorageImageReadWithoutFormat,
|
supportsImageLoadFormatted: features.ShaderStorageImageReadWithoutFormat,
|
||||||
supportsMismatchingViewFormat: true,
|
supportsMismatchingViewFormat: true,
|
||||||
supportsNonConstantTextureOffset: false,
|
supportsNonConstantTextureOffset: false,
|
||||||
|
|
Loading…
Reference in a new issue