diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs index 361b17061..d42dca28a 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Texture; +using Ryujinx.Profiler; namespace Ryujinx.Graphics.Graphics3d { @@ -40,6 +41,8 @@ namespace Ryujinx.Graphics.Graphics3d private void TextureCopy(NvGpuVmm vmm) { + Profile.Begin(Profiles.GPU.Engine2d.TextureCopy); + CopyOperation operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); int dstFormat = ReadRegister(NvGpuEngine2dReg.DstFormat); @@ -221,6 +224,8 @@ namespace Ryujinx.Graphics.Graphics3d dstBlitH); vmm.IsRegionModified(dstKey, ImageUtils.GetSize(dstTexture), NvGpuBufferType.Texture); + + Profile.End(Profiles.GPU.Engine2d.TextureCopy); } private static GalMemoryLayout GetLayout(bool linear) @@ -255,4 +260,4 @@ namespace Ryujinx.Graphics.Graphics3d return Registers[(int)reg]; } } -} \ No newline at end of file +} diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs index bbed642b8..29b6cc5df 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs @@ -5,6 +5,7 @@ using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Texture; using System; using System.Collections.Generic; +using Ryujinx.Profiler; namespace Ryujinx.Graphics.Graphics3d { @@ -89,7 +90,15 @@ namespace Ryujinx.Graphics.Graphics3d { if (_methods.TryGetValue(methCall.Method, out NvGpuMethod method)) { + ProfileConfig profile = Profiles.GPU.Engine3d.CallMethod; + + profile.SessionItem = method.Method.Name; + + Profile.Begin(profile); + method(vmm, methCall); + + Profile.End(profile); } else { @@ -99,13 +108,19 @@ namespace Ryujinx.Graphics.Graphics3d private void VertexEndGl(NvGpuVmm vmm, GpuMethodCall methCall) { + Profile.Begin(Profiles.GPU.Engine3d.VertexEnd); + LockCaches(); + Profile.Begin(Profiles.GPU.Engine3d.ConfigureState); + GalPipelineState state = new GalPipelineState(); // Framebuffer must be run configured because viewport dimensions may be used in other methods SetFrameBuffer(state); + Profile.End(Profiles.GPU.Engine3d.ConfigureState); + for (int fbIndex = 0; fbIndex < 8; fbIndex++) { SetFrameBuffer(vmm, fbIndex); @@ -135,6 +150,8 @@ namespace Ryujinx.Graphics.Graphics3d DispatchRender(vmm, state); UnlockCaches(); + + Profile.End(Profiles.GPU.Engine3d.VertexEnd); } private void LockCaches() @@ -153,6 +170,8 @@ namespace Ryujinx.Graphics.Graphics3d private void ClearBuffers(NvGpuVmm vmm, GpuMethodCall methCall) { + Profile.Begin(Profiles.GPU.Engine3d.ClearBuffers); + int attachment = (methCall.Argument >> 6) & 0xf; GalClearBufferFlags flags = (GalClearBufferFlags)(methCall.Argument & 0x3f); @@ -178,10 +197,18 @@ namespace Ryujinx.Graphics.Graphics3d _gpu.Renderer.Pipeline.ResetDepthMask(); _gpu.Renderer.Pipeline.ResetColorMask(attachment); + + Profile.End(Profiles.GPU.Engine3d.ClearBuffers); } private void SetFrameBuffer(NvGpuVmm vmm, int fbIndex) { + ProfileConfig profile = Profiles.GPU.Engine3d.SetFrameBuffer; + + profile.SessionItem = fbIndex.ToString(); + + Profile.Begin(profile); + long va = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + fbIndex * 0x10); int surfFormat = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + fbIndex * 0x10); @@ -190,6 +217,8 @@ namespace Ryujinx.Graphics.Graphics3d { _gpu.Renderer.RenderTarget.UnbindColor(fbIndex); + Profile.End(profile); + return; } @@ -227,6 +256,8 @@ namespace Ryujinx.Graphics.Graphics3d _gpu.ResourceManager.SendColorBuffer(vmm, key, fbIndex, image); _gpu.Renderer.RenderTarget.SetViewport(fbIndex, _viewportX0, _viewportY0, _viewportX1 - _viewportX0, _viewportY1 - _viewportY0); + + Profile.End(profile); } private void SetFrameBuffer(GalPipelineState state) @@ -248,6 +279,8 @@ namespace Ryujinx.Graphics.Graphics3d private void SetZeta(NvGpuVmm vmm) { + Profile.Begin(Profiles.GPU.Engine3d.SetZeta); + long va = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress); int zetaFormat = ReadRegister(NvGpuEngine3dReg.ZetaFormat); @@ -264,6 +297,8 @@ namespace Ryujinx.Graphics.Graphics3d { _gpu.Renderer.RenderTarget.UnbindZeta(); + Profile.End(Profiles.GPU.Engine3d.SetZeta); + return; } @@ -278,10 +313,14 @@ namespace Ryujinx.Graphics.Graphics3d GalImage image = new GalImage(width, height, 1, 1, 1, gobBlockHeight, 1, layout, format, GalTextureTarget.TwoD); _gpu.ResourceManager.SendZetaBuffer(vmm, key, image); + + Profile.End(Profiles.GPU.Engine3d.SetZeta); } private long[] UploadShaders(NvGpuVmm vmm) { + Profile.Begin(Profiles.GPU.Engine3d.UploadShaders); + long[] keys = new long[5]; long basePosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); @@ -339,6 +378,8 @@ namespace Ryujinx.Graphics.Graphics3d _gpu.Renderer.Shader.Bind(key); } + Profile.End(Profiles.GPU.Engine3d.UploadShaders); + return keys; } @@ -619,6 +660,8 @@ namespace Ryujinx.Graphics.Graphics3d private void UploadTextures(NvGpuVmm vmm, GalPipelineState state, long[] keys) { + Profile.Begin(Profiles.GPU.Engine3d.UploadTextures); + long baseShPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.ShaderAddress); int textureCbIndex = ReadRegister(NvGpuEngine3dReg.TextureCbIndex); @@ -660,6 +703,8 @@ namespace Ryujinx.Graphics.Graphics3d _gpu.Renderer.Texture.Bind(key, index, image); _gpu.Renderer.Texture.SetSampler(image, sampler); } + + Profile.End(Profiles.GPU.Engine3d.UploadTextures); } private (long, GalImage, GalTextureSampler) UploadTexture(NvGpuVmm vmm, int textureHandle) @@ -671,6 +716,8 @@ namespace Ryujinx.Graphics.Graphics3d return (0, default(GalImage), default(GalTextureSampler)); } + Profile.Begin(Profiles.GPU.Engine3d.UploadTexture); + bool linkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc); int ticIndex = (textureHandle >> 0) & 0xfffff; @@ -702,17 +749,23 @@ namespace Ryujinx.Graphics.Graphics3d if (key == -1) { + Profile.End(Profiles.GPU.Engine3d.UploadTexture); + //FIXME: Shouldn't ignore invalid addresses. return (0, default(GalImage), default(GalTextureSampler)); } _gpu.ResourceManager.SendTexture(vmm, key, image); + Profile.End(Profiles.GPU.Engine3d.UploadTexture); + return (key, image, sampler); } private void UploadConstBuffers(NvGpuVmm vmm, GalPipelineState state, long[] keys) { + Profile.Begin(Profiles.GPU.Engine3d.UploadConstBuffers); + for (int stage = 0; stage < keys.Length; stage++) { foreach (CBufferDescriptor desc in _gpu.Renderer.Shader.GetConstBufferUsage(keys[stage])) @@ -741,10 +794,14 @@ namespace Ryujinx.Graphics.Graphics3d state.ConstBufferKeys[stage][desc.Slot] = key; } } + + Profile.End(Profiles.GPU.Engine3d.UploadConstBuffers); } private void UploadVertexArrays(NvGpuVmm vmm, GalPipelineState state) { + Profile.Begin(Profiles.GPU.Engine3d.UploadVertexArrays); + long ibPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.IndexArrayAddress); long iboKey = vmm.GetPhysicalAddress(ibPosition); @@ -956,6 +1013,8 @@ namespace Ryujinx.Graphics.Graphics3d state.VertexBindings[index].Divisor = vertexDivisor; state.VertexBindings[index].Attribs = attribs[index].ToArray(); } + + Profile.End(Profiles.GPU.Engine3d.UploadVertexArrays); } private void DispatchRender(NvGpuVmm vmm, GalPipelineState state) diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngineM2mf.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngineM2mf.cs index 45b0bbd79..172c919bd 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngineM2mf.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngineM2mf.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Texture; using System.Collections.Generic; +using Ryujinx.Profiler; namespace Ryujinx.Graphics.Graphics3d { @@ -37,7 +38,13 @@ namespace Ryujinx.Graphics.Graphics3d { if (_methods.TryGetValue(methCall.Method, out NvGpuMethod method)) { + ProfileConfig profile = Profiles.GPU.EngineM2mf.CallMethod; + + profile.SessionItem = method.Method.Name; + + Profile.Begin(profile); method(vmm, methCall); + Profile.End(profile); } else { @@ -47,6 +54,8 @@ namespace Ryujinx.Graphics.Graphics3d private void Execute(NvGpuVmm vmm, GpuMethodCall methCall) { + Profile.Begin(Profiles.GPU.EngineM2mf.Execute); + //TODO: Some registers and copy modes are still not implemented. int control = methCall.Argument; @@ -176,6 +185,8 @@ namespace Ryujinx.Graphics.Graphics3d { vmm.Memory.CopyBytes(srcPa, dstPa, xCount); } + + Profile.End(Profiles.GPU.EngineM2mf.Execute); } private long MakeInt64From2xInt32(NvGpuEngineM2mfReg reg) @@ -200,4 +211,4 @@ namespace Ryujinx.Graphics.Graphics3d Registers[(int)reg] = value; } } -} \ No newline at end of file +} diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngineP2mf.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngineP2mf.cs index d24f2303d..83ad0e704 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngineP2mf.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngineP2mf.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Texture; using System.Collections.Generic; +using Ryujinx.Profiler; namespace Ryujinx.Graphics.Graphics3d { @@ -54,7 +55,13 @@ namespace Ryujinx.Graphics.Graphics3d { if (_methods.TryGetValue(methCall.Method, out NvGpuMethod method)) { + ProfileConfig profile = Profiles.GPU.EngineP2mf.PushData; + + profile.SessionItem = method.Method.Name; + + Profile.Begin(profile); method(vmm, methCall); + Profile.End(profile); } else { @@ -64,6 +71,8 @@ namespace Ryujinx.Graphics.Graphics3d private void Execute(NvGpuVmm vmm, GpuMethodCall methCall) { + Profile.Begin(Profiles.GPU.EngineP2mf.Execute); + //TODO: Some registers and copy modes are still not implemented. int control = methCall.Argument; @@ -97,6 +106,8 @@ namespace Ryujinx.Graphics.Graphics3d _copySize = lineLengthIn * lineCount; _buffer = new byte[_copySize]; + + Profile.End(Profiles.GPU.EngineP2mf.Execute); } private void PushData(NvGpuVmm vmm, GpuMethodCall methCall) @@ -106,6 +117,8 @@ namespace Ryujinx.Graphics.Graphics3d return; } + Profile.Begin(Profiles.GPU.EngineP2mf.PushData); + for (int shift = 0; shift < 32 && _copyOffset < _copySize; shift += 8, _copyOffset++) { _buffer[_copyOffset] = (byte)(methCall.Argument >> shift); @@ -137,6 +150,8 @@ namespace Ryujinx.Graphics.Graphics3d _buffer = null; } + + Profile.End(Profiles.GPU.EngineP2mf.PushData); } private long MakeInt64From2xInt32(NvGpuEngineP2mfReg reg) @@ -161,4 +176,4 @@ namespace Ryujinx.Graphics.Graphics3d Registers[(int)reg] = value; } } -} \ No newline at end of file +} diff --git a/Ryujinx.Profiler/ProfileConfig.cs b/Ryujinx.Profiler/ProfileConfig.cs index 6a2b2bc08..d70da6023 100644 --- a/Ryujinx.Profiler/ProfileConfig.cs +++ b/Ryujinx.Profiler/ProfileConfig.cs @@ -105,6 +105,132 @@ namespace Ryujinx.Profiler }; } + public static class GPU + { + public static class Engine2d + { + public static ProfileConfig TextureCopy = new ProfileConfig() + { + Category = "GPU.Engine2D", + SessionGroup = "TextureCopy" + }; + } + + public static class Engine3d + { + public static ProfileConfig CallMethod = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "CallMethod", + }; + + public static ProfileConfig VertexEnd = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "VertexEnd" + }; + + public static ProfileConfig ClearBuffers = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "ClearBuffers" + }; + + public static ProfileConfig SetFrameBuffer = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "SetFrameBuffer", + }; + + public static ProfileConfig SetZeta = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "SetZeta" + }; + + public static ProfileConfig UploadShaders = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "UploadShaders" + }; + + public static ProfileConfig UploadTextures = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "UploadTextures" + }; + + public static ProfileConfig UploadTexture = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "UploadTexture" + }; + + public static ProfileConfig UploadConstBuffers = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "UploadConstBuffers" + }; + + public static ProfileConfig UploadVertexArrays = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "UploadVertexArrays" + }; + + public static ProfileConfig ConfigureState = new ProfileConfig() + { + Category = "GPU.Engine3D", + SessionGroup = "ConfigureState" + }; + } + + public static class EngineM2mf + { + public static ProfileConfig CallMethod = new ProfileConfig() + { + Category = "GPU.EngineM2mf", + SessionGroup = "CallMethod", + }; + + public static ProfileConfig Execute = new ProfileConfig() + { + Category = "GPU.EngineM2mf", + SessionGroup = "Execute", + }; + } + + public static class EngineP2mf + { + public static ProfileConfig CallMethod = new ProfileConfig() + { + Category = "GPU.EngineP2mf", + SessionGroup = "CallMethod", + }; + + public static ProfileConfig Execute = new ProfileConfig() + { + Category = "GPU.EngineP2mf", + SessionGroup = "Execute", + }; + + public static ProfileConfig PushData = new ProfileConfig() + { + Category = "GPU.EngineP2mf", + SessionGroup = "PushData", + }; + } + + public static class Shader + { + public static ProfileConfig Decompile = new ProfileConfig() + { + Category = "GPU.Shader", + SessionGroup = "Decompile", + }; + } + } + public static ProfileConfig ServiceCall = new ProfileConfig() { Category = "ServiceCall",