diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs index f06c3c4b..b75ceb94 100644 --- a/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/Ryujinx.Graphics.GAL/Capabilities.cs @@ -5,20 +5,17 @@ namespace Ryujinx.Graphics.GAL public bool SupportsAstcCompression { get; } public bool SupportsNonConstantTextureOffset { get; } - public int MaximumViewportDimensions { get; } public int MaximumComputeSharedMemorySize { get; } public int StorageBufferOffsetAlignment { get; } public Capabilities( bool supportsAstcCompression, bool supportsNonConstantTextureOffset, - int maximumViewportDimensions, int maximumComputeSharedMemorySize, int storageBufferOffsetAlignment) { SupportsAstcCompression = supportsAstcCompression; SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset; - MaximumViewportDimensions = maximumViewportDimensions; MaximumComputeSharedMemorySize = maximumComputeSharedMemorySize; StorageBufferOffsetAlignment = storageBufferOffsetAlignment; } diff --git a/Ryujinx.Graphics.Gpu/Constants.cs b/Ryujinx.Graphics.Gpu/Constants.cs index ff5b9f94..65cd8846 100644 --- a/Ryujinx.Graphics.Gpu/Constants.cs +++ b/Ryujinx.Graphics.Gpu/Constants.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Gpu public const int TotalCpUniformBuffers = 8; /// - /// Maximum number of compute storage buffers (this is a API limitation). + /// Maximum number of compute storage buffers (this is an API limitation). /// public const int TotalCpStorageBuffers = 16; @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Gpu public const int TotalGpUniformBuffers = 18; /// - /// Maximum number of graphics storage buffers (this is a API limitation). + /// Maximum number of graphics storage buffers (this is an API limitation). /// public const int TotalGpStorageBuffers = 16; @@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Gpu /// /// Number of shader stages. /// - public const int TotalShaderStages = 5; + public const int ShaderStages = 5; /// /// Maximum number of vertex buffers. diff --git a/Ryujinx.Graphics.Gpu/DmaPusher.cs b/Ryujinx.Graphics.Gpu/DmaPusher.cs index d90bbd73..1c85686a 100644 --- a/Ryujinx.Graphics.Gpu/DmaPusher.cs +++ b/Ryujinx.Graphics.Gpu/DmaPusher.cs @@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.Gpu /// /// Processes a single command on the FIFO. /// - /// + /// True if the FIFO still has commands to be processed, false otherwise private bool Step() { if (_dmaGet != _dmaPut) diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs index 8418f0bb..4b6b8fd0 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs @@ -8,6 +8,9 @@ namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { + private const int NsToTicksFractionNumerator = 384; + private const int NsToTicksFractionDenominator = 625; + private ulong _runningCounter; /// @@ -103,8 +106,10 @@ namespace Ryujinx.Graphics.Gpu.Engine /// /// Converts a nanoseconds timestamp value to Maxwell time ticks. - /// The frequency is approximately 1.63Hz. /// + /// + /// The frequency is 614400000 Hz. + /// /// Timestamp in nanoseconds /// Maxwell ticks private static ulong ConvertNanosecondsToTicks(ulong nanoseconds) @@ -112,13 +117,13 @@ namespace Ryujinx.Graphics.Gpu.Engine // We need to divide first to avoid overflows. // We fix up the result later by calculating the difference and adding // that to the result. - ulong divided = nanoseconds / 625; + ulong divided = nanoseconds / NsToTicksFractionDenominator; - ulong rounded = divided * 625; + ulong rounded = divided * NsToTicksFractionDenominator; - ulong errorBias = ((nanoseconds - rounded) * 384) / 625; + ulong errorBias = (nanoseconds - rounded) * NsToTicksFractionNumerator / NsToTicksFractionDenominator; - return divided * 384 + errorBias; + return divided * NsToTicksFractionNumerator + errorBias; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 6dce61f2..d832c62e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Gpu.Engine ShaderCache = new ShaderCache(_context); - _currentProgramInfo = new ShaderProgramInfo[Constants.TotalShaderStages]; + _currentProgramInfo = new ShaderProgramInfo[Constants.ShaderStages]; BufferManager = new BufferManager(context); TextureManager = new TextureManager(context); @@ -201,7 +201,7 @@ namespace Ryujinx.Graphics.Gpu.Engine /// /// Ensures that the bindings are visible to the host GPU. - /// This actually performs the binding using the host graphics API. + /// Note: this actually performs the binding using the host graphics API. /// private void CommitBindings() { @@ -622,7 +622,7 @@ namespace Ryujinx.Graphics.Gpu.Engine /// /// Updates host render target color masks, based on guest GPU state. - /// This defines with color channels are written to each color buffer. + /// This defines which color channels are written to each color buffer. /// /// Current GPU state private void UpdateRtColorMask(GpuState state) @@ -739,7 +739,7 @@ namespace Ryujinx.Graphics.Gpu.Engine _vsUsesInstanceId = gs.Shaders[0].Program.Info.UsesInstanceId; - for (int stage = 0; stage < Constants.TotalShaderStages; stage++) + for (int stage = 0; stage < Constants.ShaderStages; stage++) { ShaderProgramInfo info = gs.Shaders[stage].Program?.Info; @@ -845,7 +845,7 @@ namespace Ryujinx.Graphics.Gpu.Engine return Target.CubemapArray; } - // TODO: Warning. + Logger.PrintWarning(LogClass.Gpu, $"Invalid sampler type \"{type}\"."); return Target.Texture2D; } @@ -855,8 +855,8 @@ namespace Ryujinx.Graphics.Gpu.Engine /// This waits until previous texture writes from the GPU to finish, before /// performing new operations with said textures. /// - /// Current GPU state - /// Method call argument + /// Current GPU state (unused) + /// Method call argument (unused) private void TextureBarrier(GpuState state, int argument) { _context.Renderer.Pipeline.TextureBarrier(); @@ -865,8 +865,8 @@ namespace Ryujinx.Graphics.Gpu.Engine /// /// Invalidates all modified textures on the cache. /// - /// Current GPU state - /// Method call argument + /// Current GPU state (unused) + /// Method call argument (unused) private void InvalidateTextures(GpuState state, int argument) { TextureManager.Flush(); @@ -880,8 +880,8 @@ namespace Ryujinx.Graphics.Gpu.Engine /// and current access has the same access patterns. /// This may be faster than the regular barrier on tile-based rasterizers. /// - /// - /// + /// Current GPU state (unused) + /// Method call argument (unused) private void TextureBarrierTiled(GpuState state, int argument) { _context.Renderer.Pipeline.TextureBarrierTiled(); diff --git a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs index fc30d03c..d66eab93 100644 --- a/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs +++ b/Ryujinx.Graphics.Gpu/Image/AutoDeleteCache.cs @@ -24,9 +24,11 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Adds a new texture to the cache, even if the texture added is already on the cache. + /// + /// /// Using this method is only recommended if you know that the texture is not yet on the cache, /// otherwise it would store the same texture more than once. - /// + /// /// The texture to be added to the cache public void Add(Texture texture) { @@ -48,9 +50,12 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Adds a new texture to the cache, or just moves it to the top of the list if the - /// texture is already on the cache. Moving the texture to the top of the list prevents - /// it from being deleted, as the textures on the bottom of the list are deleted when new ones are added. + /// texture is already on the cache. /// + /// + /// Moving the texture to the top of the list prevents it from being deleted, + /// as the textures on the bottom of the list are deleted when new ones are added. + /// /// The texture to be added, or moved to the top public void Lift(Texture texture) { diff --git a/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs b/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs index 4f73bfa8..12f3aecb 100644 --- a/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs +++ b/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs @@ -18,13 +18,19 @@ namespace Ryujinx.Graphics.Gpu.Image public Format Format { get; } /// - /// The block width for compressed formats. Must be 1 for non-compressed formats. + /// The block width for compressed formats. /// + /// + /// Must be 1 for non-compressed formats. + /// public int BlockWidth { get; } /// - /// The block height for compressed formats. Must be 1 for non-compressed formats. + /// The block height for compressed formats. /// + /// + /// Must be 1 for non-compressed formats. + /// public int BlockHeight { get; } /// diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs index bb55d40e..e4cefe9c 100644 --- a/Ryujinx.Graphics.Gpu/Image/Pool.cs +++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs @@ -17,8 +17,10 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// The maximum ID value of resources on the pool (inclusive). - /// The maximum amount of resources on the pool is equal to this value plus one. /// + /// + /// The maximum amount of resources on the pool is equal to this value plus one. + /// public int MaximumId { get; } /// diff --git a/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs b/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs index 94b3f542..1f7d9b07 100644 --- a/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs +++ b/Ryujinx.Graphics.Gpu/Image/ReductionFilter.cs @@ -2,8 +2,10 @@ namespace Ryujinx.Graphics.Gpu.Image { /// /// Represents a filter used with texture minification linear filtering. - /// This feature is only supported on NVIDIA GPUs. /// + /// + /// This feature is only supported on NVIDIA GPUs. + /// enum ReductionFilter { Average, diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 4bbefd0b..be3d622f 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -190,9 +190,11 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Changes the texture size. + /// + /// /// This operation may also change the size of all mipmap levels, including from the parent /// and other possible child textures, to ensure that all sizes are consistent. - /// + /// /// The new texture width /// The new texture height /// The new texture depth (for 3D textures) or layers (for layered textures) diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs index 94225406..91a5fcf6 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs @@ -21,8 +21,10 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Indicates if the texture is a bindless texture. - /// For those textures, Handle is ignored. /// + /// + /// For those textures, Handle is ignored. + /// public bool IsBindless { get; } /// diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index 4d50c46e..984d45a9 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Gpu.Image _texturePoolCache = texturePoolCache; _isCompute = isCompute; - int stages = isCompute ? 1 : Constants.TotalShaderStages; + int stages = isCompute ? 1 : Constants.ShaderStages; _textureBindings = new TextureBindingInfo[stages][]; _imageBindings = new TextureBindingInfo[stages][]; @@ -135,7 +135,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Ensures that the bindings are visible to the host GPU. - /// This actually performs the binding using the host graphics API. + /// Note: this actually performs the binding using the host graphics API. /// public void CommitBindings() { @@ -164,7 +164,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Ensures that the texture bindings are visible to the host GPU. - /// This actually performs the binding using the host graphics API. + /// Note: this actually performs the binding using the host graphics API. /// /// The current texture pool /// The shader stage using the textures to be bound @@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Ensures that the image bindings are visible to the host GPU. - /// This actually performs the binding using the host graphics API. + /// Note: this actually performs the binding using the host graphics API. /// /// The current texture pool /// The shader stage using the textures to be bound diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index e0a8908a..387e908d 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -753,9 +753,11 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// Removes a texture from the cache. + /// + /// /// This only removes the texture from the internal list, not from the auto-deletion cache. /// It may still have live references after the removal. - /// + /// /// The texture to be removed public void RemoveTextureFromCache(Texture texture) { diff --git a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs index cfc3815b..63a5986a 100644 --- a/Ryujinx.Graphics.Gpu/MacroInterpreter.cs +++ b/Ryujinx.Graphics.Gpu/MacroInterpreter.cs @@ -388,7 +388,7 @@ namespace Ryujinx.Graphics.Gpu /// /// Extracts a 32-bits signed integer constant from the current operation code. /// - /// + /// The 32-bits immediate value encoded at the current operation code private int GetImm() { // Note: The immediate is signed, the sign-extension is intended here. diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 8af61d3d..4210ecb9 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -53,9 +53,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Gets a sub-range from the buffer. - /// This can be used to bind and use sub-ranges of the buffer on the host API. /// - /// Start address of the sub-range, must be greater or equal to the buffer address + /// + /// This can be used to bind and use sub-ranges of the buffer on the host API. + /// + /// Start address of the sub-range, must be greater than or equal to the buffer address /// Size in bytes of the sub-range, must be less than or equal to the buffer size /// The buffer sub-range public BufferRange GetRange(ulong address, ulong size) @@ -78,9 +80,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Performs guest to host memory synchronization of the buffer data. + /// + /// /// This causes the buffer data to be overwritten if a write was detected from the CPU, /// since the last call to this method. - /// + /// /// Start address of the range to synchronize /// Size in bytes of the range to synchronize public void SynchronizeMemory(ulong address, ulong size) diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 44542349..de56baca 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -76,10 +76,10 @@ namespace Ryujinx.Graphics.Gpu.Memory _cpStorageBuffers = new BuffersPerStage(Constants.TotalCpStorageBuffers); _cpUniformBuffers = new BuffersPerStage(Constants.TotalCpUniformBuffers); - _gpStorageBuffers = new BuffersPerStage[Constants.TotalShaderStages]; - _gpUniformBuffers = new BuffersPerStage[Constants.TotalShaderStages]; + _gpStorageBuffers = new BuffersPerStage[Constants.ShaderStages]; + _gpUniformBuffers = new BuffersPerStage[Constants.ShaderStages]; - for (int index = 0; index < Constants.TotalShaderStages; index++) + for (int index = 0; index < Constants.ShaderStages; index++) { _gpStorageBuffers[index] = new BuffersPerStage(Constants.TotalGpStorageBuffers); _gpUniformBuffers[index] = new BuffersPerStage(Constants.TotalGpUniformBuffers); @@ -387,7 +387,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Ensures that the compute engine bindings are visible to the host GPU. - /// This actually performs the binding using the host graphics API. + /// Note: this actually performs the binding using the host graphics API. /// public void CommitComputeBindings() { @@ -439,7 +439,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Ensures that the graphics engine bindings are visible to the host GPU. - /// This actually performs the binding using the host graphics API. + /// Note: this actually performs the binding using the host graphics API. /// public void CommitBindings() { @@ -543,11 +543,11 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// - /// This binds buffer into the host API, or updates data for already bound buffers. + /// This binds buffers into the host API, or updates data for already bound buffers. /// /// Bindings to bind or update /// True to bind, false to update - /// True to bind as storage buffer, false to bind as uniform buffers + /// True to bind as storage buffer, false to bind as uniform buffer private void BindOrUpdateBuffers(BuffersPerStage[] bindings, bool bind, bool isStorage = false) { for (ShaderStage stage = ShaderStage.Vertex; stage <= ShaderStage.Fragment; stage++) @@ -608,8 +608,10 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Copy a buffer data from a given address to another. - /// This does a GPU side copy. /// + /// + /// This does a GPU side copy. + /// /// GPU virtual address of the copy source /// GPU virtual address of the copy destination /// Size in bytes of the copy diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs index 3cbbd253..18779333 100644 --- a/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Memory/MemoryAccessor.cs @@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Reads a structure from GPU mapped memory. /// /// Type of the structure - /// GPU virtual address where the strcture is located + /// GPU virtual address where the structure is located /// The structure at the specified memory location public T Read(ulong gpuVa) where T : struct { diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs index 33be04d3..d0171b42 100644 --- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -39,8 +39,10 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Maps a given range of pages to the specified CPU virtual address. - /// All addresses and sizes must be page aligned. /// + /// + /// All addresses and sizes must be page aligned. + /// /// CPU virtual address to map into /// GPU virtual address to be mapped /// Size in bytes of the mapping @@ -59,7 +61,7 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// - /// Maps a given range of pages to a allocated GPU virtual address. + /// Maps a given range of pages to an allocated GPU virtual address. /// The memory is automatically allocated by the memory manager. /// /// CPU virtual address to map into @@ -84,7 +86,7 @@ namespace Ryujinx.Graphics.Gpu.Memory } /// - /// Maps a given range of pages to a allocated GPU virtual address. + /// Maps a given range of pages to an allocated GPU virtual address. /// The memory is automatically allocated by the memory manager. /// This also ensures that the mapping is always done in the first 4GB of GPU address space. /// diff --git a/Ryujinx.Graphics.Gpu/Memory/RangeList.cs b/Ryujinx.Graphics.Gpu/Memory/RangeList.cs index 638108fe..d65814b3 100644 --- a/Ryujinx.Graphics.Gpu/Memory/RangeList.cs +++ b/Ryujinx.Graphics.Gpu/Memory/RangeList.cs @@ -77,9 +77,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Gets the first item on the list overlapping in memory with the specified item. + /// + /// /// Despite the name, this has no ordering guarantees of the returned item. /// It only ensures that the item returned overlaps the specified item. - /// + /// /// Item to check for overlaps /// The overlapping item, or the default value for the type if none found public T FindFirstOverlap(T item) @@ -89,9 +91,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Gets the first item on the list overlapping the specified memory range. + /// + /// /// Despite the name, this has no ordering guarantees of the returned item. /// It only ensures that the item returned overlaps the specified memory range. - /// + /// /// Start address of the range /// Size in bytes or the rangee /// The overlapping item, or the default value for the type if none found @@ -157,10 +161,12 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Gets all items overlapping with the specified item in memory. + /// + /// /// This method only returns correct results if none of the items on the list overlaps with /// each other. If that is not the case, this method should not be used. /// This method is faster than the regular method to find all overlaps. - /// + /// /// Item to check for overlaps /// Output array where matches will be written. It is automatically resized to fit the results /// The number of overlapping items found @@ -171,10 +177,12 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Gets all items on the list overlapping the specified memory range. + /// + /// /// This method only returns correct results if none of the items on the list overlaps with /// each other. If that is not the case, this method should not be used. /// This method is faster than the regular method to find all overlaps. - /// + /// /// Start address of the range /// Size in bytes or the rangee /// Output array where matches will be written. It is automatically resized to fit the results diff --git a/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs b/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs index a1493236..e348f304 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GraphicsShader.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// public GraphicsShader() { - Shaders = new CachedShader[5]; + Shaders = new CachedShader[Constants.ShaderStages]; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index 02837cbb..9f0c1c13 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Gpu.State; @@ -45,8 +46,10 @@ namespace Ryujinx.Graphics.Gpu.Shader /// /// Gets a compute shader from the cache. - /// This automatically translates, compiles and adds the code to the cache if not present. /// + /// + /// This automatically translates, compiles and adds the code to the cache if not present. + /// /// GPU virtual address of the binary shader code /// Shared memory size of the compute shader /// Local group size X of the computer shader @@ -93,8 +96,10 @@ namespace Ryujinx.Graphics.Gpu.Shader /// /// Gets a graphics shader program from the shader cache. /// This includes all the specified shader stages. - /// This automatically translates, compiles and adds the code to the cache if not present. /// + /// + /// This automatically translates, compiles and adds the code to the cache if not present. + /// /// Current GPU state /// Addresses of the shaders for each stage /// Compiled graphics shader code @@ -246,28 +251,25 @@ namespace Ryujinx.Graphics.Gpu.Shader return null; } - QueryInfoCallback queryInfo = (QueryInfoName info, int index) => + int QueryInfo(QueryInfoName info, int index) { - switch (info) + return info switch { - case QueryInfoName.ComputeLocalSizeX: - return localSizeX; - case QueryInfoName.ComputeLocalSizeY: - return localSizeY; - case QueryInfoName.ComputeLocalSizeZ: - return localSizeZ; - case QueryInfoName.ComputeSharedMemorySize: - return sharedMemorySize; - } + QueryInfoName.ComputeLocalSizeX => localSizeX, + QueryInfoName.ComputeLocalSizeY => localSizeY, + QueryInfoName.ComputeLocalSizeZ => localSizeZ, + QueryInfoName.ComputeSharedMemorySize => sharedMemorySize, + _ => QueryInfoCommon(info) + }; + } - return QueryInfoCommon(info); - }; + TranslatorCallbacks callbacks = new TranslatorCallbacks(QueryInfo, PrintLog); ShaderProgram program; Span code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize); - program = Translator.Translate(code, queryInfo, DefaultFlags | TranslationFlags.Compute); + program = Translator.Translate(code, callbacks, DefaultFlags | TranslationFlags.Compute); int[] codeCached = MemoryMarshal.Cast(code.Slice(0, program.Size)).ToArray(); @@ -284,13 +286,15 @@ namespace Ryujinx.Graphics.Gpu.Shader /// /// Translates the binary Maxwell shader code to something that the host API accepts. - /// This will combine the "Vertex A" and "Vertex B" shader stages, if specified, into one shader. /// + /// + /// This will combine the "Vertex A" and "Vertex B" shader stages, if specified, into one shader. + /// /// Current GPU state /// Shader stage /// GPU virtual address of the shader code /// Optional GPU virtual address of the "Vertex A" shader code - /// + /// Compiled graphics shader code private CachedShader TranslateGraphicsShader(GpuState state, ShaderStage stage, ulong gpuVa, ulong gpuVaA = 0) { if (gpuVa == 0) @@ -298,20 +302,18 @@ namespace Ryujinx.Graphics.Gpu.Shader return new CachedShader(null, null); } - QueryInfoCallback queryInfo = (QueryInfoName info, int index) => + int QueryInfo(QueryInfoName info, int index) { - switch (info) + return info switch { - 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(); - } + QueryInfoName.IsTextureBuffer => Convert.ToInt32(QueryIsTextureBuffer(state, (int)stage - 1, index)), + QueryInfoName.IsTextureRectangle => Convert.ToInt32(QueryIsTextureRectangle(state, (int)stage - 1, index)), + QueryInfoName.PrimitiveTopology => (int)GetPrimitiveTopology(), + _ => QueryInfoCommon(info) + }; + } - return QueryInfoCommon(info); - }; + TranslatorCallbacks callbacks = new TranslatorCallbacks(QueryInfo, PrintLog); ShaderProgram program; @@ -322,7 +324,7 @@ namespace Ryujinx.Graphics.Gpu.Shader Span codeA = _context.MemoryAccessor.Read(gpuVaA, MaxProgramSize); Span codeB = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize); - program = Translator.Translate(codeA, codeB, queryInfo, DefaultFlags); + program = Translator.Translate(codeA, codeB, callbacks, DefaultFlags); // TODO: We should also take "codeA" into account. codeCached = MemoryMarshal.Cast(codeB.Slice(0, program.Size)).ToArray(); @@ -342,7 +344,7 @@ namespace Ryujinx.Graphics.Gpu.Shader { Span code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize); - program = Translator.Translate(code, queryInfo, DefaultFlags); + program = Translator.Translate(code, callbacks, DefaultFlags); codeCached = MemoryMarshal.Cast(code.Slice(0, program.Size)).ToArray(); @@ -483,17 +485,21 @@ namespace Ryujinx.Graphics.Gpu.Shader /// Requested information private int QueryInfoCommon(QueryInfoName info) { - switch (info) + return info switch { - case QueryInfoName.MaximumViewportDimensions: - return _context.Capabilities.MaximumViewportDimensions; - case QueryInfoName.StorageBufferOffsetAlignment: - return _context.Capabilities.StorageBufferOffsetAlignment; - case QueryInfoName.SupportsNonConstantTextureOffset: - return Convert.ToInt32(_context.Capabilities.SupportsNonConstantTextureOffset); - } + QueryInfoName.StorageBufferOffsetAlignment => _context.Capabilities.StorageBufferOffsetAlignment, + QueryInfoName.SupportsNonConstantTextureOffset => Convert.ToInt32(_context.Capabilities.SupportsNonConstantTextureOffset), + _ => 0 + }; + } - return 0; + /// + /// Prints a warning from the shader code translator. + /// + /// Warning message + private static void PrintLog(string message) + { + Logger.PrintWarning(LogClass.Gpu, $"Shader translator: {message}"); } /// diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs index 8f851bca..f673d296 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuState.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs @@ -187,7 +187,7 @@ namespace Ryujinx.Graphics.Gpu.State /// /// First register offset /// Second register offset - /// Third register offset + /// Third register offset /// True if any register was modified, false otherwise public bool QueryModified(MethodOffset m1, MethodOffset m2, MethodOffset m3) { @@ -207,7 +207,7 @@ namespace Ryujinx.Graphics.Gpu.State /// /// First register offset /// Second register offset - /// Third register offset + /// Third register offset /// Fourth register offset /// True if any register was modified, false otherwise public bool QueryModified(MethodOffset m1, MethodOffset m2, MethodOffset m3, MethodOffset m4) @@ -230,7 +230,7 @@ namespace Ryujinx.Graphics.Gpu.State /// /// First register offset /// Second register offset - /// Third register offset + /// Third register offset /// Fourth register offset /// Fifth register offset /// True if any register was modified, false otherwise diff --git a/Ryujinx.Graphics.Gpu/State/GpuVa.cs b/Ryujinx.Graphics.Gpu/State/GpuVa.cs index d2ae5eb9..76a2fddf 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuVa.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuVa.cs @@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Gpu.State /// /// Packs the split address into a 64-bits address value. /// - /// + /// The 64-bits address value public ulong Pack() { return Low | ((ulong)High << 32); diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index ddc17d15..904cf8ff 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs @@ -3,6 +3,9 @@ namespace Ryujinx.Graphics.Gpu.State /// /// GPU method offset. /// + /// + /// This is indexed in 32 bits word. + /// enum MethodOffset { I2mParams = 0x60, diff --git a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index dc147484..bb8e8339 100644 --- a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -7,7 +7,6 @@ namespace Ryujinx.Graphics.OpenGL { private static Lazy _supportsAstcCompression = new Lazy(() => HasExtension("GL_KHR_texture_compression_astc_ldr")); - private static Lazy _maximumViewportDimensions = new Lazy(() => GetLimit(All.MaxViewportDims)); private static Lazy _maximumComputeSharedMemorySize = new Lazy(() => GetLimit(All.MaxComputeSharedMemorySize)); private static Lazy _storageBufferOffsetAlignment = new Lazy(() => GetLimit(All.ShaderStorageBufferOffsetAlignment)); @@ -16,7 +15,6 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsAstcCompression => _supportsAstcCompression.Value; public static bool SupportsNonConstantTextureOffset => _isNvidiaDriver.Value; - public static int MaximumViewportDimensions => _maximumViewportDimensions.Value; public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value; public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value; diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index e6021f51..86ce9c7c 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -64,7 +64,6 @@ namespace Ryujinx.Graphics.OpenGL return new Capabilities( HwCapabilities.SupportsAstcCompression, HwCapabilities.SupportsNonConstantTextureOffset, - HwCapabilities.MaximumViewportDimensions, HwCapabilities.MaximumComputeSharedMemorySize, HwCapabilities.StorageBufferOffsetAlignment); } diff --git a/Ryujinx.Graphics.OpenGL/TextureView.cs b/Ryujinx.Graphics.OpenGL/TextureView.cs index 563e0ca6..da0872f6 100644 --- a/Ryujinx.Graphics.OpenGL/TextureView.cs +++ b/Ryujinx.Graphics.OpenGL/TextureView.cs @@ -104,6 +104,7 @@ namespace Ryujinx.Graphics.OpenGL GL.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel); + // TODO: This requires ARB_stencil_texturing, we should uncomment and test this. // GL.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)_info.DepthStencilMode.Convert()); } @@ -118,7 +119,11 @@ namespace Ryujinx.Graphics.OpenGL } else { - // TODO: Improve + // TODO: Most graphics APIs doesn't support creating a texture view from a compressed format + // with a non-compressed format (or vice-versa), however NVN seems to support it. + // So we emulate that here with a texture copy (see the first CopyTo overload). + // However right now it only does a single copy right after the view is created, + // so it doesn't work for all cases. TextureView emulatedView = (TextureView)_renderer.CreateTexture(info); emulatedView._emulatedViewParent = this; diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs index da557cfa..6bef8e6c 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs @@ -91,10 +91,5 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return indentation; } - - public string GetTabString() - { - return Tab; - } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs index 866df56d..2145920e 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs @@ -86,6 +86,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { context.Barrier(); } + else + { + context.Config.PrintLog($"Invalid barrier mode: {op.Mode}."); + } } public static void Ipa(EmitterContext context) @@ -101,8 +105,6 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand srcA = Attribute(op.AttributeOffset, iq); - Operand srcB = GetSrcB(context); - Operand res = context.FPSaturate(srcA, op.Saturate); context.Copy(GetDest(context), res); @@ -128,7 +130,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (op.Size > IntegerSize.B64) { - // TODO: Warning. + context.Config.PrintLog($"Invalid LDC size: {op.Size}."); } bool isSmallInt = op.Size < IntegerSize.B32; @@ -156,7 +158,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (isSmallInt) { - value = ExtractSmallInt(context, op.Size, wordOffset, value); + value = ExtractSmallInt(context, op.Size, bitOffset, value); } context.Copy(Register(rd), value); @@ -261,7 +263,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Not supported or invalid. + context.Config.PrintLog($"Invalid reduction type: {type}."); } break; case AtomicOp.BitwiseAnd: @@ -271,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Not supported or invalid. + context.Config.PrintLog($"Invalid reduction type: {type}."); } break; case AtomicOp.BitwiseExclusiveOr: @@ -281,7 +283,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Not supported or invalid. + context.Config.PrintLog($"Invalid reduction type: {type}."); } break; case AtomicOp.BitwiseOr: @@ -291,7 +293,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Not supported or invalid. + context.Config.PrintLog($"Invalid reduction type: {type}."); } break; case AtomicOp.Maximum: @@ -305,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Not supported or invalid. + context.Config.PrintLog($"Invalid reduction type: {type}."); } break; case AtomicOp.Minimum: @@ -319,7 +321,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Not supported or invalid. + context.Config.PrintLog($"Invalid reduction type: {type}."); } break; } @@ -333,7 +335,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (op.Size > IntegerSize.B128) { - // TODO: Warning. + context.Config.PrintLog($"Invalid load size: {op.Size}."); } bool isSmallInt = op.Size < IntegerSize.B32; @@ -419,7 +421,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (op.Size > IntegerSize.B128) { - // TODO: Warning. + context.Config.PrintLog($"Invalid store size: {op.Size}."); } bool isSmallInt = op.Size < IntegerSize.B32; diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 17e80f4a..ffc4c430 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -11,8 +11,6 @@ namespace Ryujinx.Graphics.Shader.Instructions { public static void Mov(EmitterContext context) { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - context.Copy(GetDest(context), GetSrcB(context)); } @@ -33,7 +31,8 @@ namespace Ryujinx.Graphics.Shader.Instructions if (isCC) { - // TODO. + // TODO: Support Register to condition code flags copy. + context.Config.PrintLog("R2P.CC not implemented."); } else { diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs index 59096869..7b9794ea 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs @@ -18,7 +18,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (type == SamplerType.None) { - // TODO: Error, encoding is invalid. + context.Config.PrintLog("Invalid image store sampler type."); return; } @@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // TODO. + context.Config.PrintLog("Unsized image store not supported."); } Operand[] sources = sourcesList.ToArray(); @@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (type == SamplerType.None) { - // TODO: Error, encoding is invalid. + context.Config.PrintLog("Invalid texture sampler type."); return; } @@ -210,40 +210,40 @@ namespace Ryujinx.Graphics.Shader.Instructions { switch (texsOp.Target) { - case Decoders.TextureTarget.Texture1DLodZero: + case TextureTarget.Texture1DLodZero: sourcesList.Add(Ra()); break; - case Decoders.TextureTarget.Texture2D: + case TextureTarget.Texture2D: sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; - case Decoders.TextureTarget.Texture2DLodZero: + case TextureTarget.Texture2DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(ConstF(0)); break; - case Decoders.TextureTarget.Texture2DLodLevel: - case Decoders.TextureTarget.Texture2DDepthCompare: - case Decoders.TextureTarget.Texture3D: - case Decoders.TextureTarget.TextureCube: + case TextureTarget.Texture2DLodLevel: + case TextureTarget.Texture2DDepthCompare: + case TextureTarget.Texture3D: + case TextureTarget.TextureCube: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; - case Decoders.TextureTarget.Texture2DLodZeroDepthCompare: - case Decoders.TextureTarget.Texture3DLodZero: + case TextureTarget.Texture2DLodZeroDepthCompare: + case TextureTarget.Texture3DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(ConstF(0)); break; - case Decoders.TextureTarget.Texture2DLodLevelDepthCompare: - case Decoders.TextureTarget.TextureCubeLodLevel: + case TextureTarget.Texture2DLodLevelDepthCompare: + case TextureTarget.TextureCubeLodLevel: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); @@ -258,7 +258,7 @@ namespace Ryujinx.Graphics.Shader.Instructions if (type == SamplerType.None) { - // TODO: Error, encoding is invalid. + context.Config.PrintLog("Invalid texel fetch sampler type."); return; } @@ -742,8 +742,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { OpCodeTexture op = (OpCodeTexture)context.CurrOp; - bool isBindless = (flags & TextureFlags.Bindless) != 0; - bool intCoords = (flags & TextureFlags.IntCoords) != 0; + bool isBindless = (flags & TextureFlags.Bindless) != 0; if (op.Rd.IsRZ) { @@ -920,36 +919,36 @@ namespace Ryujinx.Graphics.Shader.Instructions throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\"."); } - private static SamplerType ConvertSamplerType(Decoders.TextureTarget type) + private static SamplerType ConvertSamplerType(TextureTarget type) { switch (type) { - case Decoders.TextureTarget.Texture1DLodZero: + case TextureTarget.Texture1DLodZero: return SamplerType.Texture1D; - case Decoders.TextureTarget.Texture2D: - case Decoders.TextureTarget.Texture2DLodZero: - case Decoders.TextureTarget.Texture2DLodLevel: + case TextureTarget.Texture2D: + case TextureTarget.Texture2DLodZero: + case TextureTarget.Texture2DLodLevel: return SamplerType.Texture2D; - case Decoders.TextureTarget.Texture2DDepthCompare: - case Decoders.TextureTarget.Texture2DLodLevelDepthCompare: - case Decoders.TextureTarget.Texture2DLodZeroDepthCompare: + case TextureTarget.Texture2DDepthCompare: + case TextureTarget.Texture2DLodLevelDepthCompare: + case TextureTarget.Texture2DLodZeroDepthCompare: return SamplerType.Texture2D | SamplerType.Shadow; - case Decoders.TextureTarget.Texture2DArray: - case Decoders.TextureTarget.Texture2DArrayLodZero: + case TextureTarget.Texture2DArray: + case TextureTarget.Texture2DArrayLodZero: return SamplerType.Texture2D | SamplerType.Array; - case Decoders.TextureTarget.Texture2DArrayLodZeroDepthCompare: + case TextureTarget.Texture2DArrayLodZeroDepthCompare: return SamplerType.Texture2D | SamplerType.Array | SamplerType.Shadow; - case Decoders.TextureTarget.Texture3D: - case Decoders.TextureTarget.Texture3DLodZero: + case TextureTarget.Texture3D: + case TextureTarget.Texture3DLodZero: return SamplerType.Texture3D; - case Decoders.TextureTarget.TextureCube: - case Decoders.TextureTarget.TextureCubeLodLevel: + case TextureTarget.TextureCube: + case TextureTarget.TextureCubeLodLevel: return SamplerType.TextureCube; } @@ -987,22 +986,22 @@ namespace Ryujinx.Graphics.Shader.Instructions { switch (type) { - case Decoders.TextureTarget.Texture1DLodZero: - case Decoders.TextureTarget.Texture2DLodZero: - case Decoders.TextureTarget.Texture2DLodLevel: - case Decoders.TextureTarget.Texture2DLodLevelDepthCompare: - case Decoders.TextureTarget.Texture2DLodZeroDepthCompare: - case Decoders.TextureTarget.Texture2DArrayLodZero: - case Decoders.TextureTarget.Texture2DArrayLodZeroDepthCompare: - case Decoders.TextureTarget.Texture3DLodZero: - case Decoders.TextureTarget.TextureCubeLodLevel: + case TextureTarget.Texture1DLodZero: + case TextureTarget.Texture2DLodZero: + case TextureTarget.Texture2DLodLevel: + case TextureTarget.Texture2DLodLevelDepthCompare: + case TextureTarget.Texture2DLodZeroDepthCompare: + case TextureTarget.Texture2DArrayLodZero: + case TextureTarget.Texture2DArrayLodZeroDepthCompare: + case TextureTarget.Texture3DLodZero: + case TextureTarget.TextureCubeLodLevel: return TextureFlags.LodLevel; - case Decoders.TextureTarget.Texture2D: - case Decoders.TextureTarget.Texture2DDepthCompare: - case Decoders.TextureTarget.Texture2DArray: - case Decoders.TextureTarget.Texture3D: - case Decoders.TextureTarget.TextureCube: + case TextureTarget.Texture2D: + case TextureTarget.Texture2DDepthCompare: + case TextureTarget.Texture2DArray: + case TextureTarget.Texture3D: + case TextureTarget.TextureCube: return TextureFlags.None; } diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs index 9c4d5f1a..8f81ecb4 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs @@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - // Invalid. + context.Config.PrintLog($"Invalid vote operation: {op.VoteOp}."); } if (!op.Rd.IsRZ) diff --git a/Ryujinx.Graphics.Shader/QueryInfoCallback.cs b/Ryujinx.Graphics.Shader/QueryInfoCallback.cs deleted file mode 100644 index 28261a77..00000000 --- a/Ryujinx.Graphics.Shader/QueryInfoCallback.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Ryujinx.Graphics.Shader -{ - public delegate int QueryInfoCallback(QueryInfoName info, int index); -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/QueryInfoName.cs b/Ryujinx.Graphics.Shader/QueryInfoName.cs index 1d87c2c8..c4f2cb6c 100644 --- a/Ryujinx.Graphics.Shader/QueryInfoName.cs +++ b/Ryujinx.Graphics.Shader/QueryInfoName.cs @@ -8,7 +8,6 @@ namespace Ryujinx.Graphics.Shader ComputeSharedMemorySize, IsTextureBuffer, IsTextureRectangle, - MaximumViewportDimensions, PrimitiveTopology, StorageBufferOffsetAlignment, SupportsNonConstantTextureOffset diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs index e6334fea..fbe19765 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs @@ -13,6 +13,8 @@ namespace Ryujinx.Graphics.Shader.Translation private ShaderConfig _config; + public ShaderConfig Config => _config; + private List _operations; private Dictionary _labels; diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs index d73a268e..8a0f25fe 100644 --- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs +++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs @@ -16,30 +16,30 @@ namespace Ryujinx.Graphics.Shader.Translation public TranslationFlags Flags { get; } - private QueryInfoCallback _queryInfoCallback; + private TranslatorCallbacks _callbacks; - public ShaderConfig(TranslationFlags flags, QueryInfoCallback queryInfoCallback) + public ShaderConfig(TranslationFlags flags, TranslatorCallbacks callbacks) { - Stage = ShaderStage.Compute; - OutputTopology = OutputTopology.PointList; - MaxOutputVertices = 0; - OmapTargets = null; - OmapSampleMask = false; - OmapDepth = false; - Flags = flags; - _queryInfoCallback = queryInfoCallback; + Stage = ShaderStage.Compute; + OutputTopology = OutputTopology.PointList; + MaxOutputVertices = 0; + OmapTargets = null; + OmapSampleMask = false; + OmapDepth = false; + Flags = flags; + _callbacks = callbacks; } - public ShaderConfig(ShaderHeader header, TranslationFlags flags, QueryInfoCallback queryInfoCallback) + public ShaderConfig(ShaderHeader header, TranslationFlags flags, TranslatorCallbacks callbacks) { - Stage = header.Stage; - OutputTopology = header.OutputTopology; - MaxOutputVertices = header.MaxOutputVertexCount; - OmapTargets = header.OmapTargets; - OmapSampleMask = header.OmapSampleMask; - OmapDepth = header.OmapDepth; - Flags = flags; - _queryInfoCallback = queryInfoCallback; + Stage = header.Stage; + OutputTopology = header.OutputTopology; + MaxOutputVertices = header.MaxOutputVertexCount; + OmapTargets = header.OmapTargets; + OmapSampleMask = header.OmapSampleMask; + OmapDepth = header.OmapDepth; + Flags = flags; + _callbacks = callbacks; } public int GetDepthRegister() @@ -68,9 +68,9 @@ namespace Ryujinx.Graphics.Shader.Translation public int QueryInfo(QueryInfoName info, int index = 0) { - if (_queryInfoCallback != null) + if (_callbacks.QueryInfo != null) { - return _queryInfoCallback(info, index); + return _callbacks.QueryInfo(info, index); } else { @@ -86,8 +86,6 @@ namespace Ryujinx.Graphics.Shader.Translation return Convert.ToInt32(false); case QueryInfoName.IsTextureRectangle: return Convert.ToInt32(false); - case QueryInfoName.MaximumViewportDimensions: - return 0x8000; case QueryInfoName.PrimitiveTopology: return (int)InputTopology.Points; case QueryInfoName.StorageBufferOffsetAlignment: @@ -99,5 +97,10 @@ namespace Ryujinx.Graphics.Shader.Translation return 0; } + + public void PrintLog(string message) + { + _callbacks.PrintLog?.Invoke(message); + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs index af209edf..bdc6a094 100644 --- a/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -40,21 +40,17 @@ namespace Ryujinx.Graphics.Shader.Translation return code.Slice(0, headerSize + (int)endAddress); } - public static ShaderProgram Translate(Span code, QueryInfoCallback queryInfoCallback, TranslationFlags flags) + public static ShaderProgram Translate(Span code, TranslatorCallbacks callbacks, TranslationFlags flags) { - bool compute = (flags & TranslationFlags.Compute) != 0; - - Operation[] ops = DecodeShader(code, queryInfoCallback, flags, out ShaderConfig config, out int size); + Operation[] ops = DecodeShader(code, callbacks, flags, out ShaderConfig config, out int size); return Translate(ops, config, size); } - public static ShaderProgram Translate(Span vpACode, Span vpBCode, QueryInfoCallback queryInfoCallback, TranslationFlags flags) + public static ShaderProgram Translate(Span vpACode, Span vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags) { - bool debugMode = (flags & TranslationFlags.DebugMode) != 0; - - Operation[] vpAOps = DecodeShader(vpACode, queryInfoCallback, flags, out _, out _); - Operation[] vpBOps = DecodeShader(vpBCode, queryInfoCallback, flags, out ShaderConfig config, out int sizeB); + Operation[] vpAOps = DecodeShader(vpACode, callbacks, flags, out _, out _); + Operation[] vpBOps = DecodeShader(vpBCode, callbacks, flags, out ShaderConfig config, out int sizeB); return Translate(Combine(vpAOps, vpBOps), config, sizeB); } @@ -94,34 +90,34 @@ namespace Ryujinx.Graphics.Shader.Translation } private static Operation[] DecodeShader( - Span code, - QueryInfoCallback queryInfoCallback, - TranslationFlags flags, - out ShaderConfig config, - out int size) + Span code, + TranslatorCallbacks callbacks, + TranslationFlags flags, + out ShaderConfig config, + out int size) { Block[] cfg; if ((flags & TranslationFlags.Compute) != 0) { - config = new ShaderConfig(flags, queryInfoCallback); + config = new ShaderConfig(flags, callbacks); cfg = Decoder.Decode(code, 0); } else { - config = new ShaderConfig(new ShaderHeader(code), flags, queryInfoCallback); + config = new ShaderConfig(new ShaderHeader(code), flags, callbacks); cfg = Decoder.Decode(code, HeaderSize); } if (cfg == null) { - // TODO: Error. + config.PrintLog("Invalid branch detected, failed to build CFG."); size = 0; - return new Operation[0]; + return Array.Empty(); } EmitterContext context = new EmitterContext(config); @@ -156,6 +152,8 @@ namespace Ryujinx.Graphics.Shader.Translation else { instName = "???"; + + config.PrintLog($"Invalid instruction at 0x{op.Address:X6} (0x{op.RawOpCode:X16})."); } string dbgComment = $"0x{op.Address:X6}: 0x{op.RawOpCode:X16} {instName}"; @@ -210,10 +208,7 @@ namespace Ryujinx.Graphics.Shader.Translation context.CurrOp = op; - if (op.Emitter != null) - { - op.Emitter(context); - } + op.Emitter?.Invoke(context); if (predSkipLbl != null) { diff --git a/Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs b/Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs new file mode 100644 index 00000000..e0e9852f --- /dev/null +++ b/Ryujinx.Graphics.Shader/Translation/TranslatorCallbacks.cs @@ -0,0 +1,17 @@ +using System; + +namespace Ryujinx.Graphics.Shader.Translation +{ + public struct TranslatorCallbacks + { + internal Func QueryInfo { get; } + + internal Action PrintLog { get; } + + public TranslatorCallbacks(Func queryInfoCallback, Action printLogCallback) + { + QueryInfo = queryInfoCallback; + PrintLog = printLogCallback; + } + } +} diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index 69c5364b..2c4d0112 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -405,14 +405,14 @@ namespace Ryujinx.Ui /// An supported by this machine private static IAalOutput InitializeAudioEngine() { - /*if (SoundIoAudioOut.IsSupported) - { - return new SoundIoAudioOut(); - } - else*/ if (OpenALAudioOut.IsSupported) + if (OpenALAudioOut.IsSupported) { return new OpenALAudioOut(); } + else if (SoundIoAudioOut.IsSupported) + { + return new SoundIoAudioOut(); + } else { return new DummyAudioOut();