diff options
author | gdkchan <gab.dark.100@gmail.com> | 2019-12-16 01:59:46 -0300 |
---|---|---|
committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
commit | 9d7a142a48a5f804127fcae2265bb6ec5495d178 (patch) | |
tree | 4ba4de906d74404760fcbebe9aeb51460252f500 /Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | |
parent | 2eccc7023ae0d1247378516b14507d422e4915c5 (diff) |
Support texture rectangle targets (non-normalized coords)
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 181 |
1 files changed, 108 insertions, 73 deletions
diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index 648e073c..422cc597 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -1,10 +1,10 @@ using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Gpu.State; using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; using System; using System.Collections.Generic; -using System.Globalization; using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Gpu.Shader @@ -13,6 +13,8 @@ namespace Ryujinx.Graphics.Gpu.Shader { private const int MaxProgramSize = 0x100000; + private const TranslationFlags DefaultFlags = TranslationFlags.DebugMode; + private GpuContext _context; private ShaderDumper _dumper; @@ -69,7 +71,7 @@ namespace Ryujinx.Graphics.Gpu.Shader return cpShader; } - public GraphicsShader GetGraphicsShader(ShaderAddresses addresses, bool dividePosXY) + public GraphicsShader GetGraphicsShader(GpuState state, ShaderAddresses addresses) { bool isCached = _gpPrograms.TryGetValue(addresses, out List<GraphicsShader> list); @@ -86,28 +88,19 @@ namespace Ryujinx.Graphics.Gpu.Shader GraphicsShader gpShaders = new GraphicsShader(); - TranslationFlags flags = - TranslationFlags.DebugMode | - TranslationFlags.Unspecialized; - - if (dividePosXY) - { - flags |= TranslationFlags.DividePosXY; - } - if (addresses.VertexA != 0) { - gpShaders.Shader[0] = TranslateGraphicsShader(flags, addresses.Vertex, addresses.VertexA); + gpShaders.Shader[0] = TranslateGraphicsShader(state, ShaderStage.Vertex, addresses.Vertex, addresses.VertexA); } else { - gpShaders.Shader[0] = TranslateGraphicsShader(flags, addresses.Vertex); + gpShaders.Shader[0] = TranslateGraphicsShader(state, ShaderStage.Vertex, addresses.Vertex); } - gpShaders.Shader[1] = TranslateGraphicsShader(flags, addresses.TessControl); - gpShaders.Shader[2] = TranslateGraphicsShader(flags, addresses.TessEvaluation); - gpShaders.Shader[3] = TranslateGraphicsShader(flags, addresses.Geometry); - gpShaders.Shader[4] = TranslateGraphicsShader(flags, addresses.Fragment); + gpShaders.Shader[1] = TranslateGraphicsShader(state, ShaderStage.TessellationControl, addresses.TessControl); + gpShaders.Shader[2] = TranslateGraphicsShader(state, ShaderStage.TessellationEvaluation, addresses.TessEvaluation); + gpShaders.Shader[3] = TranslateGraphicsShader(state, ShaderStage.Geometry, addresses.Geometry); + gpShaders.Shader[4] = TranslateGraphicsShader(state, ShaderStage.Fragment, addresses.Fragment); BackpropQualifiers(gpShaders); @@ -199,25 +192,31 @@ namespace Ryujinx.Graphics.Gpu.Shader return null; } - ShaderProgram program; + QueryInfoCallback queryInfo = (QueryInfoName info, int index) => + { + switch (info) + { + case QueryInfoName.ComputeLocalSizeX: + return localSizeX; + case QueryInfoName.ComputeLocalSizeY: + return localSizeY; + case QueryInfoName.ComputeLocalSizeZ: + return localSizeZ; + case QueryInfoName.ComputeSharedMemorySize: + return sharedMemorySize; + } - const TranslationFlags flags = - TranslationFlags.Compute | - TranslationFlags.DebugMode | - TranslationFlags.Unspecialized; + return QueryInfoCommon(info); + }; + + ShaderProgram program; Span<byte> code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize); - program = Translator.Translate(code, GetShaderCapabilities(), flags); + program = Translator.Translate(code, queryInfo, DefaultFlags | TranslationFlags.Compute); int[] codeCached = MemoryMarshal.Cast<byte, int>(code.Slice(0, program.Size)).ToArray(); - program.Replace(DefineNames.SharedMemorySize, (sharedMemorySize / 4).ToString(CultureInfo.InvariantCulture)); - - program.Replace(DefineNames.LocalSizeX, localSizeX.ToString(CultureInfo.InvariantCulture)); - program.Replace(DefineNames.LocalSizeY, localSizeY.ToString(CultureInfo.InvariantCulture)); - program.Replace(DefineNames.LocalSizeZ, localSizeZ.ToString(CultureInfo.InvariantCulture)); - _dumper.Dump(code, compute: true, out string fullPath, out string codePath); if (fullPath != null && codePath != null) @@ -229,13 +228,30 @@ namespace Ryujinx.Graphics.Gpu.Shader return new CachedShader(program, codeCached); } - private CachedShader TranslateGraphicsShader(TranslationFlags flags, ulong gpuVa, ulong gpuVaA = 0) + private CachedShader TranslateGraphicsShader(GpuState state, ShaderStage stage, ulong gpuVa, ulong gpuVaA = 0) { if (gpuVa == 0) { return new CachedShader(null, null); } + QueryInfoCallback queryInfo = (QueryInfoName info, int index) => + { + switch (info) + { + case QueryInfoName.IsTextureBuffer: + return Convert.ToInt32(QueryIsTextureBuffer(state, (int)stage - 1, index)); + case QueryInfoName.IsTextureRectangle: + return Convert.ToInt32(QueryIsTextureRectangle(state, (int)stage - 1, index)); + case QueryInfoName.PrimitiveTopology: + return (int)GetPrimitiveTopology(); + case QueryInfoName.ViewportTransformEnable: + return Convert.ToInt32(_context.Methods.GetViewportTransformEnable(state)); + } + + return QueryInfoCommon(info); + }; + ShaderProgram program; int[] codeCached = null; @@ -245,9 +261,9 @@ namespace Ryujinx.Graphics.Gpu.Shader Span<byte> codeA = _context.MemoryAccessor.Read(gpuVaA, MaxProgramSize); Span<byte> codeB = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize); - program = Translator.Translate(codeA, codeB, GetShaderCapabilities(), flags); + program = Translator.Translate(codeA, codeB, queryInfo, DefaultFlags); - // TODO: We should also check "codeA" into account. + // TODO: We should also take "codeA" into account. codeCached = MemoryMarshal.Cast<byte, int>(codeB.Slice(0, program.Size)).ToArray(); _dumper.Dump(codeA, compute: false, out string fullPathA, out string codePathA); @@ -265,7 +281,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { Span<byte> code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize); - program = Translator.Translate(code, GetShaderCapabilities(), flags); + program = Translator.Translate(code, queryInfo, DefaultFlags); codeCached = MemoryMarshal.Cast<byte, int>(code.Slice(0, program.Size)).ToArray(); @@ -278,40 +294,6 @@ namespace Ryujinx.Graphics.Gpu.Shader } } - if (program.Stage == ShaderStage.Geometry) - { - PrimitiveType primitiveType = _context.Methods.PrimitiveType; - - string inPrimitive = "points"; - - switch (primitiveType) - { - case PrimitiveType.Points: - inPrimitive = "points"; - break; - case PrimitiveType.Lines: - case PrimitiveType.LineLoop: - case PrimitiveType.LineStrip: - inPrimitive = "lines"; - break; - case PrimitiveType.LinesAdjacency: - case PrimitiveType.LineStripAdjacency: - inPrimitive = "lines_adjacency"; - break; - case PrimitiveType.Triangles: - case PrimitiveType.TriangleStrip: - case PrimitiveType.TriangleFan: - inPrimitive = "triangles"; - break; - case PrimitiveType.TrianglesAdjacency: - case PrimitiveType.TriangleStripAdjacency: - inPrimitive = "triangles_adjacency"; - break; - } - - program.Replace(DefineNames.InputTopologyName, inPrimitive); - } - ulong address = _context.MemoryManager.Translate(gpuVa); return new CachedShader(program, codeCached); @@ -350,13 +332,66 @@ namespace Ryujinx.Graphics.Gpu.Shader } } - private ShaderCapabilities GetShaderCapabilities() + private InputTopology GetPrimitiveTopology() + { + switch (_context.Methods.PrimitiveType) + { + case PrimitiveType.Points: + return InputTopology.Points; + case PrimitiveType.Lines: + case PrimitiveType.LineLoop: + case PrimitiveType.LineStrip: + return InputTopology.Lines; + case PrimitiveType.LinesAdjacency: + case PrimitiveType.LineStripAdjacency: + return InputTopology.LinesAdjacency; + case PrimitiveType.Triangles: + case PrimitiveType.TriangleStrip: + case PrimitiveType.TriangleFan: + return InputTopology.Triangles; + case PrimitiveType.TrianglesAdjacency: + case PrimitiveType.TriangleStripAdjacency: + return InputTopology.TrianglesAdjacency; + } + + return InputTopology.Points; + } + + private bool QueryIsTextureBuffer(GpuState state, int stageIndex, int index) + { + return GetTextureDescriptor(state, stageIndex, index).UnpackTextureTarget() == TextureTarget.TextureBuffer; + } + + private bool QueryIsTextureRectangle(GpuState state, int stageIndex, int index) { - return new ShaderCapabilities( - _context.Capabilities.MaximumViewportDimensions, - _context.Capabilities.MaximumComputeSharedMemorySize, - _context.Capabilities.StorageBufferOffsetAlignment, - _context.Capabilities.SupportsNonConstantTextureOffset); + var descriptor = GetTextureDescriptor(state, stageIndex, index); + + TextureTarget target = descriptor.UnpackTextureTarget(); + + bool is2DTexture = target == TextureTarget.Texture2D || + target == TextureTarget.Texture2DRect; + + return !descriptor.UnpackTextureCoordNormalized() && is2DTexture; + } + + private Image.TextureDescriptor GetTextureDescriptor(GpuState state, int stageIndex, int index) + { + return _context.Methods.TextureManager.GetGraphicsTextureDescriptor(state, stageIndex, index); + } + + private int QueryInfoCommon(QueryInfoName info) + { + switch (info) + { + case QueryInfoName.MaximumViewportDimensions: + return _context.Capabilities.MaximumViewportDimensions; + case QueryInfoName.StorageBufferOffsetAlignment: + return _context.Capabilities.StorageBufferOffsetAlignment; + case QueryInfoName.SupportsNonConstantTextureOffset: + return Convert.ToInt32(_context.Capabilities.SupportsNonConstantTextureOffset); + } + + return 0; } } }
\ No newline at end of file |