/ src / Ryujinx.Graphics.Vulkan / DescriptorSetTemplateUpdater.cs
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  }