diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs
index f06c3c4b41..b75ceb94f3 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 ff5b9f94c9..65cd8846d4 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 d90bbd7318..1c85686a52 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 8418f0bb57..4b6b8fd0a3 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 6dce61f2b3..d832c62e7b 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 fc30d03c77..d66eab93f0 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 4f73bfa867..12f3aecbbd 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 bb55d40e1d..e4cefe9cbc 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 94b3f54255..1f7d9b0703 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 4bbefd0bc6..be3d622f9c 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 94225406ef..91a5fcf60e 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 4d50c46e30..984d45a952 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 e0a8908aa0..387e908d69 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 cfc3815b0d..63a5986ac4 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 8af61d3d82..4210ecb982 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 44542349d9..de56bacaf4 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 3cbbd25361..1877933317 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 33be04d398..d0171b4205 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 638108fe7f..d65814b3f1 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 a149323649..e348f304f3 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 02837cbb14..9f0c1c1332 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 8f851bca54..f673d296c8 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 d2ae5eb9e1..76a2fddfd2 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 ddc17d1549..904cf8ff49 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 dc147484dd..bb8e8339b6 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 e6021f51f7..86ce9c7cdd 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 563e0ca61e..da0872f6d3 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 da557cfa8b..6bef8e6c20 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 866df56dfb..2145920ef8 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 17e80f4a4a..ffc4c430f5 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 59096869ed..7b9794eaf1 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 9c4d5f1af7..8f81ecb4df 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 28261a77e2..0000000000
--- 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 1d87c2c881..c4f2cb6cc2 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 e6334feaf6..fbe197651e 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 d73a268e96..8a0f25fe45 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 af209edf1d..bdc6a094f7 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 0000000000..e0e9852fa3
--- /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 69c5364b4e..2c4d011268 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();