DescriptorSetTemplateUpdater.cs
1 using Ryujinx.Common; 2 using Silk.NET.Vulkan; 3 using System; 4 using System.Runtime.CompilerServices; 5 using System.Runtime.InteropServices; 6 7 namespace Ryujinx.Graphics.Vulkan 8 { 9 ref struct DescriptorSetTemplateWriter 10 { 11 private Span<byte> _data; 12 13 public DescriptorSetTemplateWriter(Span<byte> data) 14 { 15 _data = data; 16 } 17 18 public void Push<T>(ReadOnlySpan<T> values) where T : unmanaged 19 { 20 Span<T> target = MemoryMarshal.Cast<byte, T>(_data); 21 22 values.CopyTo(target); 23 24 _data = _data[(Unsafe.SizeOf<T>() * values.Length)..]; 25 } 26 } 27 28 unsafe class DescriptorSetTemplateUpdater : IDisposable 29 { 30 private const int SizeGranularity = 512; 31 32 private DescriptorSetTemplate _activeTemplate; 33 private NativeArray<byte> _data; 34 35 private void EnsureSize(int size) 36 { 37 if (_data == null || _data.Length < size) 38 { 39 _data?.Dispose(); 40 41 int dataSize = BitUtils.AlignUp(size, SizeGranularity); 42 _data = new NativeArray<byte>(dataSize); 43 } 44 } 45 46 public DescriptorSetTemplateWriter Begin(DescriptorSetTemplate template) 47 { 48 _activeTemplate = template; 49 50 EnsureSize(template.Size); 51 52 return new DescriptorSetTemplateWriter(new Span<byte>(_data.Pointer, template.Size)); 53 } 54 55 public DescriptorSetTemplateWriter Begin(int maxSize) 56 { 57 EnsureSize(maxSize); 58 59 return new DescriptorSetTemplateWriter(new Span<byte>(_data.Pointer, maxSize)); 60 } 61 62 public void Commit(VulkanRenderer gd, Device device, DescriptorSet set) 63 { 64 gd.Api.UpdateDescriptorSetWithTemplate(device, set, _activeTemplate.Template, _data.Pointer); 65 } 66 67 public void CommitPushDescriptor(VulkanRenderer gd, CommandBufferScoped cbs, DescriptorSetTemplate template, PipelineLayout layout) 68 { 69 gd.PushDescriptorApi.CmdPushDescriptorSetWithTemplate(cbs.CommandBuffer, template.Template, layout, 0, _data.Pointer); 70 } 71 72 public void Dispose() 73 { 74 _data?.Dispose(); 75 } 76 } 77 }