f82309fa2d
* 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>
103 lines
No EOL
2.9 KiB
C#
103 lines
No EOL
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);
|
|
}
|
|
} |