diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs')
| -rw-r--r-- | src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs new file mode 100644 index 00000000..3e816733 --- /dev/null +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -0,0 +1,297 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu.Image; +using Ryujinx.Graphics.Shader; +using Ryujinx.Graphics.Shader.Translation; +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Gpu.Shader +{ + /// <summary> + /// Represents a GPU state and memory accessor. + /// </summary> + class GpuAccessor : GpuAccessorBase, IGpuAccessor + { + private readonly GpuChannel _channel; + private readonly GpuAccessorState _state; + private readonly int _stageIndex; + private readonly bool _compute; + private readonly bool _isVulkan; + + /// <summary> + /// Creates a new instance of the GPU state accessor for graphics shader translation. + /// </summary> + /// <param name="context">GPU context</param> + /// <param name="channel">GPU channel</param> + /// <param name="state">Current GPU state</param> + /// <param name="stageIndex">Graphics shader stage index (0 = Vertex, 4 = Fragment)</param> + public GpuAccessor( + GpuContext context, + GpuChannel channel, + GpuAccessorState state, + int stageIndex) : base(context, state.ResourceCounts, stageIndex) + { + _isVulkan = context.Capabilities.Api == TargetApi.Vulkan; + _channel = channel; + _state = state; + _stageIndex = stageIndex; + } + + /// <summary> + /// Creates a new instance of the GPU state accessor for compute shader translation. + /// </summary> + /// <param name="context">GPU context</param> + /// <param name="channel">GPU channel</param> + /// <param name="state">Current GPU state</param> + public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context, state.ResourceCounts, 0) + { + _channel = channel; + _state = state; + _compute = true; + } + + /// <inheritdoc/> + public uint ConstantBuffer1Read(int offset) + { + ulong baseAddress = _compute + ? _channel.BufferManager.GetComputeUniformBufferAddress(1) + : _channel.BufferManager.GetGraphicsUniformBufferAddress(_stageIndex, 1); + + return _channel.MemoryManager.Physical.Read<uint>(baseAddress + (ulong)offset); + } + + /// <inheritdoc/> + public void Log(string message) + { + Logger.Warning?.Print(LogClass.Gpu, $"Shader translator: {message}"); + } + + /// <inheritdoc/> + public ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize) + { + int size = Math.Max(minimumSize, 0x1000 - (int)(address & 0xfff)); + return MemoryMarshal.Cast<byte, ulong>(_channel.MemoryManager.GetSpan(address, size)); + } + + /// <inheritdoc/> + public bool QueryAlphaToCoverageDitherEnable() + { + return _state.GraphicsState.AlphaToCoverageEnable && _state.GraphicsState.AlphaToCoverageDitherEnable; + } + + /// <inheritdoc/> + public AlphaTestOp QueryAlphaTestCompare() + { + if (!_isVulkan || !_state.GraphicsState.AlphaTestEnable) + { + return AlphaTestOp.Always; + } + + return _state.GraphicsState.AlphaTestCompare switch + { + CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never, + CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less, + CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal, + CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual, + CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater, + CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual, + CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual, + _ => AlphaTestOp.Always + }; + } + + /// <inheritdoc/> + public float QueryAlphaTestReference() + { + return _state.GraphicsState.AlphaTestReference; + } + + /// <inheritdoc/> + public AttributeType QueryAttributeType(int location) + { + return _state.GraphicsState.AttributeTypes[location]; + } + + /// <inheritdoc/> + public AttributeType QueryFragmentOutputType(int location) + { + return _state.GraphicsState.FragmentOutputTypes[location]; + } + + /// <inheritdoc/> + public int QueryComputeLocalSizeX() => _state.ComputeState.LocalSizeX; + + /// <inheritdoc/> + public int QueryComputeLocalSizeY() => _state.ComputeState.LocalSizeY; + + /// <inheritdoc/> + public int QueryComputeLocalSizeZ() => _state.ComputeState.LocalSizeZ; + + /// <inheritdoc/> + public int QueryComputeLocalMemorySize() => _state.ComputeState.LocalMemorySize; + + /// <inheritdoc/> + public int QueryComputeSharedMemorySize() => _state.ComputeState.SharedMemorySize; + + /// <inheritdoc/> + public uint QueryConstantBufferUse() + { + uint useMask = _compute + ? _channel.BufferManager.GetComputeUniformBufferUseMask() + : _channel.BufferManager.GetGraphicsUniformBufferUseMask(_stageIndex); + + _state.SpecializationState?.RecordConstantBufferUse(_stageIndex, useMask); + return useMask; + } + + /// <inheritdoc/> + public bool QueryHasConstantBufferDrawParameters() + { + return _state.GraphicsState.HasConstantBufferDrawParameters; + } + + /// <inheritdoc/> + public bool QueryHasUnalignedStorageBuffer() + { + return _state.GraphicsState.HasUnalignedStorageBuffer || _state.ComputeState.HasUnalignedStorageBuffer; + } + + /// <inheritdoc/> + public bool QueryDualSourceBlendEnable() + { + return _state.GraphicsState.DualSourceBlendEnable; + } + + /// <inheritdoc/> + public InputTopology QueryPrimitiveTopology() + { + _state.SpecializationState?.RecordPrimitiveTopology(); + return ConvertToInputTopology(_state.GraphicsState.Topology, _state.GraphicsState.TessellationMode); + } + + /// <inheritdoc/> + public bool QueryProgramPointSize() + { + return _state.GraphicsState.ProgramPointSizeEnable; + } + + /// <inheritdoc/> + public float QueryPointSize() + { + return _state.GraphicsState.PointSize; + } + + /// <inheritdoc/> + public bool QueryTessCw() + { + return _state.GraphicsState.TessellationMode.UnpackCw(); + } + + /// <inheritdoc/> + public TessPatchType QueryTessPatchType() + { + return _state.GraphicsState.TessellationMode.UnpackPatchType(); + } + + /// <inheritdoc/> + public TessSpacing QueryTessSpacing() + { + return _state.GraphicsState.TessellationMode.UnpackSpacing(); + } + + //// <inheritdoc/> + public TextureFormat QueryTextureFormat(int handle, int cbufSlot) + { + _state.SpecializationState?.RecordTextureFormat(_stageIndex, handle, cbufSlot); + var descriptor = GetTextureDescriptor(handle, cbufSlot); + return ConvertToTextureFormat(descriptor.UnpackFormat(), descriptor.UnpackSrgb()); + } + + /// <inheritdoc/> + public SamplerType QuerySamplerType(int handle, int cbufSlot) + { + _state.SpecializationState?.RecordTextureSamplerType(_stageIndex, handle, cbufSlot); + return GetTextureDescriptor(handle, cbufSlot).UnpackTextureTarget().ConvertSamplerType(); + } + + /// <inheritdoc/> + public bool QueryTextureCoordNormalized(int handle, int cbufSlot) + { + _state.SpecializationState?.RecordTextureCoordNormalized(_stageIndex, handle, cbufSlot); + return GetTextureDescriptor(handle, cbufSlot).UnpackTextureCoordNormalized(); + } + + /// <summary> + /// Gets the texture descriptor for a given texture on the pool. + /// </summary> + /// <param name="handle">Index of the texture (this is the word offset of the handle in the constant buffer)</param> + /// <param name="cbufSlot">Constant buffer slot for the texture handle</param> + /// <returns>Texture descriptor</returns> + private Image.TextureDescriptor GetTextureDescriptor(int handle, int cbufSlot) + { + if (_compute) + { + return _channel.TextureManager.GetComputeTextureDescriptor( + _state.PoolState.TexturePoolGpuVa, + _state.PoolState.TextureBufferIndex, + _state.PoolState.TexturePoolMaximumId, + handle, + cbufSlot); + } + else + { + return _channel.TextureManager.GetGraphicsTextureDescriptor( + _state.PoolState.TexturePoolGpuVa, + _state.PoolState.TextureBufferIndex, + _state.PoolState.TexturePoolMaximumId, + _stageIndex, + handle, + cbufSlot); + } + } + + /// <inheritdoc/> + public bool QueryTransformDepthMinusOneToOne() + { + return _state.GraphicsState.DepthMode; + } + + /// <inheritdoc/> + public bool QueryTransformFeedbackEnabled() + { + return _state.TransformFeedbackDescriptors != null; + } + + /// <inheritdoc/> + public ReadOnlySpan<byte> QueryTransformFeedbackVaryingLocations(int bufferIndex) + { + return _state.TransformFeedbackDescriptors[bufferIndex].AsSpan(); + } + + /// <inheritdoc/> + public int QueryTransformFeedbackStride(int bufferIndex) + { + return _state.TransformFeedbackDescriptors[bufferIndex].Stride; + } + + /// <inheritdoc/> + public bool QueryEarlyZForce() + { + _state.SpecializationState?.RecordEarlyZForce(); + return _state.GraphicsState.EarlyZForce; + } + + /// <inheritdoc/> + public bool QueryViewportTransformDisable() + { + return _state.GraphicsState.ViewportTransformDisable; + } + + /// <inheritdoc/> + public void RegisterTexture(int handle, int cbufSlot) + { + _state.SpecializationState?.RegisterTexture(_stageIndex, handle, cbufSlot, GetTextureDescriptor(handle, cbufSlot)); + } + } +} |
