Compare commits

..

7 Commits

Author SHA1 Message Date
riperiperi
04d68ca616 GPU: Ensure all clip distances are initialized when used (#7363)
* GPU: Ensure all clip distances are initialized when used

* Shader cache version
2024-09-26 14:19:12 -03:00
Jason Youngberg
050f22977f Update bug_report.yml to provide better instructions for finding log file (#7333) 2024-09-24 11:10:36 +02:00
gdkchan
319507f2a1 Fix quads draws after DrawTexture on Vulkan (#7336) 2024-09-22 19:36:53 -03:00
gdkchan
d717aef2be Shader: Assume the only remaining source is the right one when all others are undefined (#7331)
* Shader: Assume the only remaining source is the right one when all other are undefined

* Shader cache version bump

* Improve comment
2024-09-19 21:23:09 -03:00
gdkchan
24ee8c39f1 Add support for sampler sRGB disable (#7312) 2024-09-19 14:38:30 -03:00
jhorv
73f985d27c Replace passing by IMemoryOwner<byte> with passing by concrete MemoryOwner<byte> (#7171)
* refactor(perf): pass MemoryOwner<byte> around as itself rather than IMemoryOwner<byte>

* fix(perf): get span via MemoryOwner<byte>.Span property instead of through Memory property

* fix: incorrect comment change
2024-09-18 23:00:54 -03:00
gdkchan
ef81658fbd Implement support for shader ATOM.EXCH instruction (#7320)
* Implement support for shader ATOM.EXCH instruction

* Shader cache version bump

* Check type
2024-09-18 15:48:55 -03:00
24 changed files with 204 additions and 120 deletions

View File

@@ -23,7 +23,7 @@ body:
attributes:
label: Log file
description: A log file will help our developers to better diagnose and fix the issue.
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. You can drag and drop the log on to the text area
placeholder: Logs files can be found under "Logs" folder in Ryujinx program folder. They can also be accessed by opening Ryujinx, then going to File > Open Logs Folder. You can drag and drop the log on to the text area (do not copy paste).
validations:
required: true
- type: input
@@ -83,4 +83,4 @@ body:
- Additional info about your environment:
- Any other information relevant to your issue.
validations:
required: false
required: false

View File

@@ -1,4 +1,4 @@
using System.Buffers;
using Ryujinx.Common.Memory;
namespace Ryujinx.Graphics.GAL
{
@@ -18,30 +18,30 @@ namespace Ryujinx.Graphics.GAL
PinnedSpan<byte> GetData(int layer, int level);
/// <summary>
/// Sets the texture data. The data passed as a <see cref="IMemoryOwner{Byte}" /> will be disposed when
/// Sets the texture data. The data passed as a <see cref="MemoryOwner{Byte}" /> will be disposed when
/// the operation completes.
/// </summary>
/// <param name="data">Texture data bytes</param>
void SetData(IMemoryOwner<byte> data);
void SetData(MemoryOwner<byte> data);
/// <summary>
/// Sets the texture data. The data passed as a <see cref="IMemoryOwner{Byte}" /> will be disposed when
/// Sets the texture data. The data passed as a <see cref="MemoryOwner{Byte}" /> will be disposed when
/// the operation completes.
/// </summary>
/// <param name="data">Texture data bytes</param>
/// <param name="layer">Target layer</param>
/// <param name="level">Target level</param>
void SetData(IMemoryOwner<byte> data, int layer, int level);
void SetData(MemoryOwner<byte> data, int layer, int level);
/// <summary>
/// Sets the texture data. The data passed as a <see cref="IMemoryOwner{Byte}" /> will be disposed when
/// Sets the texture data. The data passed as a <see cref="MemoryOwner{Byte}" /> will be disposed when
/// the operation completes.
/// </summary>
/// <param name="data">Texture data bytes</param>
/// <param name="layer">Target layer</param>
/// <param name="level">Target level</param>
/// <param name="region">Target sub-region of the texture to update</param>
void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region);
void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region);
void SetStorage(BufferRange buffer);

View File

@@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
@@ -8,9 +8,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
public readonly CommandType CommandType => CommandType.TextureSetData;
private TableRef<ThreadedTexture> _texture;
private TableRef<IMemoryOwner<byte>> _data;
private TableRef<MemoryOwner<byte>> _data;
public void Set(TableRef<ThreadedTexture> texture, TableRef<IMemoryOwner<byte>> data)
public void Set(TableRef<ThreadedTexture> texture, TableRef<MemoryOwner<byte>> data)
{
_texture = texture;
_data = data;

View File

@@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
@@ -8,11 +8,11 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
public readonly CommandType CommandType => CommandType.TextureSetDataSlice;
private TableRef<ThreadedTexture> _texture;
private TableRef<IMemoryOwner<byte>> _data;
private TableRef<MemoryOwner<byte>> _data;
private int _layer;
private int _level;
public void Set(TableRef<ThreadedTexture> texture, TableRef<IMemoryOwner<byte>> data, int layer, int level)
public void Set(TableRef<ThreadedTexture> texture, TableRef<MemoryOwner<byte>> data, int layer, int level)
{
_texture = texture;
_data = data;

View File

@@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
@@ -8,12 +8,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
{
public readonly CommandType CommandType => CommandType.TextureSetDataSliceRegion;
private TableRef<ThreadedTexture> _texture;
private TableRef<IMemoryOwner<byte>> _data;
private TableRef<MemoryOwner<byte>> _data;
private int _layer;
private int _level;
private Rectangle<int> _region;
public void Set(TableRef<ThreadedTexture> texture, TableRef<IMemoryOwner<byte>> data, int layer, int level, Rectangle<int> region)
public void Set(TableRef<ThreadedTexture> texture, TableRef<MemoryOwner<byte>> data, int layer, int level, Rectangle<int> region)
{
_texture = texture;
_data = data;

View File

@@ -1,6 +1,6 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL.Multithreading.Commands.Texture;
using Ryujinx.Graphics.GAL.Multithreading.Model;
using System.Buffers;
namespace Ryujinx.Graphics.GAL.Multithreading.Resources
{
@@ -111,21 +111,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data)
public void SetData(MemoryOwner<byte> data)
{
_renderer.New<TextureSetDataCommand>().Set(Ref(this), Ref(data));
_renderer.QueueCommand();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level)
public void SetData(MemoryOwner<byte> data, int layer, int level)
{
_renderer.New<TextureSetDataSliceCommand>().Set(Ref(this), Ref(data), layer, level);
_renderer.QueueCommand();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{
_renderer.New<TextureSetDataSliceRegionCommand>().Set(Ref(this), Ref(data), layer, level, region);
_renderer.QueueCommand();

View File

@@ -1,10 +1,10 @@
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.Gpu.Engine.Threed;
using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -353,7 +353,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
if (target != null)
{
IMemoryOwner<byte> data;
MemoryOwner<byte> data;
if (srcLinear)
{
data = LayoutConverter.ConvertLinearStridedToLinear(

View File

@@ -13,6 +13,11 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
public bool IsDisposed { get; private set; }
/// <summary>
/// True if the sampler has sRGB conversion enabled, false otherwise.
/// </summary>
public bool IsSrgb { get; }
/// <summary>
/// Host sampler object.
/// </summary>
@@ -30,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="descriptor">The Maxwell sampler descriptor</param>
public Sampler(GpuContext context, SamplerDescriptor descriptor)
{
IsSrgb = descriptor.UnpackSrgb();
MinFilter minFilter = descriptor.UnpackMinFilter();
MagFilter magFilter = descriptor.UnpackMagFilter();

View File

@@ -113,6 +113,15 @@ namespace Ryujinx.Graphics.Gpu.Image
return (CompareOp)(((Word0 >> 10) & 7) + 1);
}
/// <summary>
/// Unpacks the sampler sRGB format flag.
/// </summary>
/// <returns>True if the has sampler is sRGB conversion enabled, false otherwise</returns>
public readonly bool UnpackSrgb()
{
return (Word0 & (1 << 13)) != 0;
}
/// <summary>
/// Unpacks and converts the maximum anisotropy value used for texture anisotropic filtering.
/// </summary>

View File

@@ -7,7 +7,6 @@ using Ryujinx.Graphics.Texture.Astc;
using Ryujinx.Memory;
using Ryujinx.Memory.Range;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -662,7 +661,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
IMemoryOwner<byte> result = ConvertToHostCompatibleFormat(data);
MemoryOwner<byte> result = ConvertToHostCompatibleFormat(data);
if (ScaleFactor != 1f && AllowScaledSetData())
{
@@ -685,7 +684,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Uploads new texture data to the host GPU.
/// </summary>
/// <param name="data">New data</param>
public void SetData(IMemoryOwner<byte> data)
public void SetData(MemoryOwner<byte> data)
{
BlacklistScale();
@@ -704,7 +703,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="data">New data</param>
/// <param name="layer">Target layer</param>
/// <param name="level">Target level</param>
public void SetData(IMemoryOwner<byte> data, int layer, int level)
public void SetData(MemoryOwner<byte> data, int layer, int level)
{
BlacklistScale();
@@ -722,7 +721,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="layer">Target layer</param>
/// <param name="level">Target level</param>
/// <param name="region">Target sub-region of the texture to update</param>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{
BlacklistScale();
@@ -740,7 +739,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="level">Mip level to convert</param>
/// <param name="single">True to convert a single slice</param>
/// <returns>Converted data</returns>
public IMemoryOwner<byte> ConvertToHostCompatibleFormat(ReadOnlySpan<byte> data, int level = 0, bool single = false)
public MemoryOwner<byte> ConvertToHostCompatibleFormat(ReadOnlySpan<byte> data, int level = 0, bool single = false)
{
int width = Info.Width;
int height = Info.Height;
@@ -755,7 +754,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int sliceDepth = single ? 1 : depth;
IMemoryOwner<byte> linear;
MemoryOwner<byte> linear;
if (Info.IsLinear)
{
@@ -788,7 +787,7 @@ namespace Ryujinx.Graphics.Gpu.Image
data);
}
IMemoryOwner<byte> result = linear;
MemoryOwner<byte> result = linear;
// Handle compressed cases not supported by the host:
// - ASTC is usually not supported on desktop cards.
@@ -832,19 +831,19 @@ namespace Ryujinx.Graphics.Gpu.Image
case Format.Etc2RgbaUnorm:
using (result)
{
return ETC2Decoder.DecodeRgba(result.Memory.Span, width, height, sliceDepth, levels, layers);
return ETC2Decoder.DecodeRgba(result.Span, width, height, sliceDepth, levels, layers);
}
case Format.Etc2RgbPtaSrgb:
case Format.Etc2RgbPtaUnorm:
using (result)
{
return ETC2Decoder.DecodePta(result.Memory.Span, width, height, sliceDepth, levels, layers);
return ETC2Decoder.DecodePta(result.Span, width, height, sliceDepth, levels, layers);
}
case Format.Etc2RgbSrgb:
case Format.Etc2RgbUnorm:
using (result)
{
return ETC2Decoder.DecodeRgb(result.Memory.Span, width, height, sliceDepth, levels, layers);
return ETC2Decoder.DecodeRgb(result.Span, width, height, sliceDepth, levels, layers);
}
}
}
@@ -856,43 +855,43 @@ namespace Ryujinx.Graphics.Gpu.Image
case Format.Bc1RgbaUnorm:
using (result)
{
return BCnDecoder.DecodeBC1(result.Memory.Span, width, height, sliceDepth, levels, layers);
return BCnDecoder.DecodeBC1(result.Span, width, height, sliceDepth, levels, layers);
}
case Format.Bc2Srgb:
case Format.Bc2Unorm:
using (result)
{
return BCnDecoder.DecodeBC2(result.Memory.Span, width, height, sliceDepth, levels, layers);
return BCnDecoder.DecodeBC2(result.Span, width, height, sliceDepth, levels, layers);
}
case Format.Bc3Srgb:
case Format.Bc3Unorm:
using (result)
{
return BCnDecoder.DecodeBC3(result.Memory.Span, width, height, sliceDepth, levels, layers);
return BCnDecoder.DecodeBC3(result.Span, width, height, sliceDepth, levels, layers);
}
case Format.Bc4Snorm:
case Format.Bc4Unorm:
using (result)
{
return BCnDecoder.DecodeBC4(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm);
return BCnDecoder.DecodeBC4(result.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc4Snorm);
}
case Format.Bc5Snorm:
case Format.Bc5Unorm:
using (result)
{
return BCnDecoder.DecodeBC5(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm);
return BCnDecoder.DecodeBC5(result.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc5Snorm);
}
case Format.Bc6HSfloat:
case Format.Bc6HUfloat:
using (result)
{
return BCnDecoder.DecodeBC6(result.Memory.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat);
return BCnDecoder.DecodeBC6(result.Span, width, height, sliceDepth, levels, layers, Format == Format.Bc6HSfloat);
}
case Format.Bc7Srgb:
case Format.Bc7Unorm:
using (result)
{
return BCnDecoder.DecodeBC7(result.Memory.Span, width, height, sliceDepth, levels, layers);
return BCnDecoder.DecodeBC7(result.Span, width, height, sliceDepth, levels, layers);
}
}
}
@@ -900,7 +899,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
using (result)
{
var converted = PixelConverter.ConvertR4G4ToR4G4B4A4(result.Memory.Span, width);
var converted = PixelConverter.ConvertR4G4ToR4G4B4A4(result.Span, width);
if (_context.Capabilities.SupportsR4G4B4A4Format)
{
@@ -910,7 +909,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
using (converted)
{
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(converted.Memory.Span, width);
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(converted.Span, width);
}
}
}
@@ -921,7 +920,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
using (result)
{
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Memory.Span, width);
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Span, width);
}
}
}
@@ -933,24 +932,24 @@ namespace Ryujinx.Graphics.Gpu.Image
case Format.R5G6B5Unorm:
using (result)
{
return PixelConverter.ConvertR5G6B5ToR8G8B8A8(result.Memory.Span, width);
return PixelConverter.ConvertR5G6B5ToR8G8B8A8(result.Span, width);
}
case Format.B5G5R5A1Unorm:
case Format.R5G5B5X1Unorm:
case Format.R5G5B5A1Unorm:
using (result)
{
return PixelConverter.ConvertR5G5B5ToR8G8B8A8(result.Memory.Span, width, Format == Format.R5G5B5X1Unorm);
return PixelConverter.ConvertR5G5B5ToR8G8B8A8(result.Span, width, Format == Format.R5G5B5X1Unorm);
}
case Format.A1B5G5R5Unorm:
using (result)
{
return PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result.Memory.Span, width);
return PixelConverter.ConvertA1B5G5R5ToR8G8B8A8(result.Span, width);
}
case Format.R4G4B4A4Unorm:
using (result)
{
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Memory.Span, width);
return PixelConverter.ConvertR4G4B4A4ToR8G8B8A8(result.Span, width);
}
}
}

View File

@@ -187,7 +187,9 @@ namespace Ryujinx.Graphics.Gpu.Image
{
(TexturePool texturePool, SamplerPool samplerPool) = GetPools();
return (texturePool.Get(textureId), samplerPool.Get(samplerId));
Sampler sampler = samplerPool?.Get(samplerId);
return (texturePool.Get(textureId, sampler?.IsSrgb ?? true), sampler);
}
/// <summary>
@@ -508,12 +510,12 @@ namespace Ryujinx.Graphics.Gpu.Image
state.TextureHandle = textureId;
state.SamplerHandle = samplerId;
ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, out Texture texture);
Sampler sampler = samplerPool?.Get(samplerId);
ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, sampler?.IsSrgb ?? true, out Texture texture);
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
Sampler sampler = samplerPool?.Get(samplerId);
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
ISampler hostSampler = sampler?.GetHostSampler(texture);

View File

@@ -1,3 +1,4 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture;
@@ -5,7 +6,6 @@ using Ryujinx.Memory;
using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
@@ -445,7 +445,7 @@ namespace Ryujinx.Graphics.Gpu.Image
ReadOnlySpan<byte> data = dataSpan[(offset - spanBase)..];
IMemoryOwner<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true);
MemoryOwner<byte> result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true);
Storage.SetData(result, info.BaseLayer + layer, info.BaseLevel + level);
}

View File

@@ -227,6 +227,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
/// <returns>The texture with the given ID</returns>
public override Texture Get(int id)
{
return Get(id, srgbSampler: true);
}
/// <summary>
/// Gets the texture with the given ID.
/// </summary>
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
/// <param name="srgbSampler">Whether the texture is being accessed with a sampler that has sRGB conversion enabled</param>
/// <returns>The texture with the given ID</returns>
public Texture Get(int id, bool srgbSampler)
{
if ((uint)id >= Items.Length)
{
@@ -240,7 +251,7 @@ namespace Ryujinx.Graphics.Gpu.Image
SynchronizeMemory();
}
GetInternal(id, out Texture texture);
GetForBinding(id, srgbSampler, out Texture texture);
return texture;
}
@@ -252,9 +263,10 @@ namespace Ryujinx.Graphics.Gpu.Image
/// This method assumes that the pool has been manually synchronized before doing binding.
/// </remarks>
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
/// <param name="srgbSampler">Whether the texture is being accessed with a sampler that has sRGB conversion enabled</param>
/// <param name="texture">The texture with the given ID</param>
/// <returns>The texture descriptor with the given ID</returns>
public ref readonly TextureDescriptor GetForBinding(int id, out Texture texture)
public ref readonly TextureDescriptor GetForBinding(int id, bool srgbSampler, out Texture texture)
{
if ((uint)id >= Items.Length)
{
@@ -264,6 +276,18 @@ namespace Ryujinx.Graphics.Gpu.Image
// When getting for binding, assume the pool has already been synchronized.
if (!srgbSampler)
{
// If the sampler does not have the sRGB bit enabled, then the texture can't use a sRGB format.
ref readonly TextureDescriptor tempDescriptor = ref GetDescriptorRef(id);
if (tempDescriptor.UnpackSrgb() && FormatTable.TryGetTextureFormat(tempDescriptor.UnpackFormat(), isSrgb: false, out FormatInfo formatInfo))
{
// Get a view of the texture with the right format.
return ref GetForBinding(id, formatInfo, out texture);
}
}
return ref GetInternal(id, out texture);
}

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 7131;
private const uint CodeGenVersion = 7353;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View File

@@ -1,7 +1,7 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using System;
using System.Buffers;
namespace Ryujinx.Graphics.OpenGL.Image
{
@@ -55,9 +55,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data)
public void SetData(MemoryOwner<byte> data)
{
var dataSpan = data.Memory.Span;
var dataSpan = data.Span;
Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
@@ -65,13 +65,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level)
public void SetData(MemoryOwner<byte> data, int layer, int level)
{
throw new NotSupportedException();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{
throw new NotSupportedException();
}

View File

@@ -1,8 +1,8 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using System;
using System.Buffers;
using System.Diagnostics;
namespace Ryujinx.Graphics.OpenGL.Image
@@ -448,13 +448,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
public void SetData(IMemoryOwner<byte> data)
public void SetData(MemoryOwner<byte> data)
{
using (data = EnsureDataFormat(data))
{
unsafe
{
var dataSpan = data.Memory.Span;
var dataSpan = data.Span;
fixed (byte* ptr = dataSpan)
{
ReadFrom((IntPtr)ptr, dataSpan.Length);
@@ -463,13 +463,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
public void SetData(IMemoryOwner<byte> data, int layer, int level)
public void SetData(MemoryOwner<byte> data, int layer, int level)
{
using (data = EnsureDataFormat(data))
{
unsafe
{
fixed (byte* ptr = data.Memory.Span)
fixed (byte* ptr = data.Span)
{
int width = Math.Max(Info.Width >> level, 1);
int height = Math.Max(Info.Height >> level, 1);
@@ -480,7 +480,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{
using (data = EnsureDataFormat(data))
{
@@ -489,7 +489,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
unsafe
{
fixed (byte* ptr = data.Memory.Span)
fixed (byte* ptr = data.Span)
{
ReadFrom2D(
(IntPtr)ptr,
@@ -522,13 +522,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
ReadFrom2D(data, layer, level, x, y, width, height, mipSize);
}
private IMemoryOwner<byte> EnsureDataFormat(IMemoryOwner<byte> data)
private MemoryOwner<byte> EnsureDataFormat(MemoryOwner<byte> data)
{
if (Format == Format.S8UintD24Unorm)
{
using (data)
{
return FormatConverter.ConvertS8D24ToD24S8(data.Memory.Span);
return FormatConverter.ConvertS8D24ToD24S8(data.Span);
}
}

View File

@@ -222,30 +222,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.And:
if (type == AtomSize.S32 || type == AtomSize.U32)
case AtomOp.Min:
if (type == AtomSize.S32)
{
res = context.AtomicAnd(storageKind, e0, e1, value);
res = context.AtomicMinS32(storageKind, e0, e1, value);
}
else
else if (type == AtomSize.U32)
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Xor:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicXor(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Or:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicOr(storageKind, e0, e1, value);
res = context.AtomicMinU32(storageKind, e0, e1, value);
}
else
{
@@ -266,20 +250,49 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Min:
if (type == AtomSize.S32)
case AtomOp.And:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicMinS32(storageKind, e0, e1, value);
}
else if (type == AtomSize.U32)
{
res = context.AtomicMinU32(storageKind, e0, e1, value);
res = context.AtomicAnd(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Or:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicOr(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Xor:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicXor(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Exch:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicSwap(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
default:
context.TranslatorContext.GpuAccessor.Log($"Invalid atomic operation: {op}.");
break;
}
return res;

View File

@@ -138,6 +138,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// Ensure that conditions met for that branch are also met for the current one.
// Prefer the latest sources for the phi node.
int undefCount = 0;
for (int i = phiNode.SourcesCount - 1; i >= 0; i--)
{
BasicBlock phiBlock = phiNode.GetBlock(i);
@@ -159,6 +161,26 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return match;
}
}
else if (phiSource.Type == OperandType.Undefined)
{
undefCount++;
}
}
// If all sources but one are undefined, we can assume that the one
// that is not undefined is the right one.
if (undefCount == phiNode.SourcesCount - 1)
{
for (int i = phiNode.SourcesCount - 1; i >= 0; i--)
{
Operand phiSource = phiNode.GetSource(i);
if (phiSource.Type != OperandType.Undefined)
{
return phiSource;
}
}
}
}

View File

@@ -190,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (stage == ShaderStage.Vertex)
{
InitializePositionOutput(context);
InitializeVertexOutputs(context);
}
UInt128 usedAttributes = context.TranslatorContext.AttributeUsage.NextInputAttributesComponents;
@@ -236,12 +236,20 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
private static void InitializePositionOutput(EmitterContext context)
private static void InitializeVertexOutputs(EmitterContext context)
{
for (int c = 0; c < 4; c++)
{
context.Store(StorageKind.Output, IoVariable.Position, null, Const(c), ConstF(c == 3 ? 1f : 0f));
}
if (context.Program.ClipDistancesWritten != 0)
{
for (int i = 0; i < 8; i++)
{
context.Store(StorageKind.Output, IoVariable.ClipDistance, null, Const(i), ConstF(0f));
}
}
}
private static void InitializeOutput(EmitterContext context, int location, bool perPatch)

View File

@@ -636,9 +636,9 @@ namespace Ryujinx.Graphics.Vulkan
var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable;
var oldDepthWriteEnable = _newState.DepthWriteEnable;
var oldTopology = _newState.Topology;
var oldViewports = DynamicState.Viewports;
var oldViewportsCount = _newState.ViewportsCount;
var oldTopology = _topology;
_newState.CullMode = CullModeFlags.None;
_newState.StencilTestEnable = false;
@@ -658,7 +658,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.StencilTestEnable = oldStencilTestEnable;
_newState.DepthTestEnable = oldDepthTestEnable;
_newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology;
SetPrimitiveTopology(oldTopology);
DynamicState.SetViewports(ref oldViewports, oldViewportsCount);

View File

@@ -1,7 +1,7 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan;
using System;
using System.Buffers;
using System.Collections.Generic;
using Format = Ryujinx.Graphics.GAL.Format;
using VkFormat = Silk.NET.Vulkan.Format;
@@ -84,20 +84,20 @@ namespace Ryujinx.Graphics.Vulkan
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data)
public void SetData(MemoryOwner<byte> data)
{
_gd.SetBufferData(_bufferHandle, _offset, data.Memory.Span);
_gd.SetBufferData(_bufferHandle, _offset, data.Span);
data.Dispose();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level)
public void SetData(MemoryOwner<byte> data, int layer, int level)
{
throw new NotSupportedException();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{
throw new NotSupportedException();
}

View File

@@ -1,7 +1,7 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -746,23 +746,23 @@ namespace Ryujinx.Graphics.Vulkan
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data)
public void SetData(MemoryOwner<byte> data)
{
SetData(data.Memory.Span, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false);
SetData(data.Span, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false);
data.Dispose();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level)
public void SetData(MemoryOwner<byte> data, int layer, int level)
{
SetData(data.Memory.Span, layer, level, 1, 1, singleSlice: true);
SetData(data.Span, layer, level, 1, 1, singleSlice: true);
data.Dispose();
}
/// <inheritdoc/>
public void SetData(IMemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
public void SetData(MemoryOwner<byte> data, int layer, int level, Rectangle<int> region)
{
SetData(data.Memory.Span, layer, level, 1, 1, singleSlice: true, region);
SetData(data.Span, layer, level, 1, 1, singleSlice: true, region);
data.Dispose();
}

View File

@@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
private readonly MemoryOwner<byte> _rawDataOwner;
private Span<byte> Raw => _rawDataOwner.Memory.Span;
private Span<byte> Raw => _rawDataOwner.Span;
private ref ParcelHeader Header => ref MemoryMarshal.Cast<byte, ParcelHeader>(Raw)[0];

View File

@@ -1,5 +1,5 @@
using Ryujinx.Common.Memory;
using System;
using System.Buffers;
namespace Ryujinx.Memory
{
@@ -7,7 +7,7 @@ namespace Ryujinx.Memory
{
private readonly IWritableBlock _block;
private readonly ulong _va;
private readonly IMemoryOwner<byte> _memoryOwner;
private readonly MemoryOwner<byte> _memoryOwner;
private readonly bool _tracked;
private bool NeedsWriteback => _block != null;
@@ -22,7 +22,7 @@ namespace Ryujinx.Memory
Memory = memory;
}
public WritableRegion(IWritableBlock block, ulong va, IMemoryOwner<byte> memoryOwner, bool tracked = false)
public WritableRegion(IWritableBlock block, ulong va, MemoryOwner<byte> memoryOwner, bool tracked = false)
: this(block, va, memoryOwner.Memory, tracked)
{
_memoryOwner = memoryOwner;