aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-12-16 01:59:46 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit9d7a142a48a5f804127fcae2265bb6ec5495d178 (patch)
tree4ba4de906d74404760fcbebe9aeb51460252f500 /Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
parent2eccc7023ae0d1247378516b14507d422e4915c5 (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.cs181
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