Ryujinx/Ryujinx.Graphics.Vulkan/SpecInfo.cs
gdkchan f82309fa2d
Vulkan: Implement multisample <-> non-multisample copies and depth-stencil resolve (#3723)
* Vulkan: Implement multisample <-> non-multisample copies and depth-stencil resolve

* FramebufferParams is no longer required there

* Implement Specialization Constants and merge CopyMS Shaders (#15)

* Vulkan: Initial Specialization Constants

* Replace with specialized helper shader

* Reimplement everything

Fix nonexistant interaction with Ryu pipeline caching
Decouple specialization info from data and relocate them
Generalize mapping and add type enum to better match spv types
Use local fixed scopes instead of global unmanaged allocs

* Fix misses in initial implementation

Use correct info variable in Create2DLayerView
Add ShaderStorageImageMultisample to required feature set

* Use texture for source image

* No point in using ReadOnlyMemory

* Apply formatting feedback

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Apply formatting suggestions on shader source

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Support conversion with samples count that does not match the requested count, other minor changes

Co-authored-by: mageven <62494521+mageven@users.noreply.github.com>
2022-11-02 18:17:19 -03:00

103 lines
2.9 KiB
C#

using Silk.NET.Vulkan;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Vulkan
{
public enum SpecConstType
{
Bool32,
Int16,
Int32,
Int64,
Float16,
Float32,
Float64
}
sealed class SpecDescription
{
public readonly SpecializationInfo Info;
public readonly SpecializationMapEntry[] Map;
// For mapping a simple packed struct or single entry
public SpecDescription(params (uint Id, SpecConstType Type)[] description)
{
int count = description.Length;
Map = new SpecializationMapEntry[count];
uint structSize = 0;
for (int i = 0; i < count; ++i)
{
var typeSize = SizeOf(description[i].Type);
Map[i] = new SpecializationMapEntry(description[i].Id, structSize, typeSize);
structSize += typeSize;
}
Info = new SpecializationInfo()
{
DataSize = structSize,
MapEntryCount = (uint)count
};
}
// For advanced mapping with overlapping or staggered fields
public SpecDescription(SpecializationMapEntry[] map)
{
int count = map.Length;
Map = map;
uint structSize = 0;
for (int i = 0; i < count; ++i)
{
structSize = Math.Max(structSize, map[i].Offset + (uint)map[i].Size);
}
Info = new SpecializationInfo()
{
DataSize = structSize,
MapEntryCount = (uint)map.Length
};
}
private static uint SizeOf(SpecConstType type) => type switch
{
SpecConstType.Int16 or SpecConstType.Float16 => 2,
SpecConstType.Bool32 or SpecConstType.Int32 or SpecConstType.Float32 => 4,
SpecConstType.Int64 or SpecConstType.Float64 => 8,
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
private SpecDescription()
{
Info = new();
}
public static readonly SpecDescription Empty = new();
}
readonly struct SpecData : IRefEquatable<SpecData>
{
private readonly byte[] _data;
private readonly int _hash;
public int Length => _data.Length;
public ReadOnlySpan<byte> Span => _data.AsSpan();
public override int GetHashCode() => _hash;
public SpecData(ReadOnlySpan<byte> data)
{
_data = new byte[data.Length];
data.CopyTo(_data);
var hc = new HashCode();
hc.AddBytes(data);
_hash = hc.ToHashCode();
}
public override bool Equals(object obj) => obj is SpecData other && Equals(other);
public bool Equals(ref SpecData other) => _data.AsSpan().SequenceEqual(other._data);
}
}