VulkanRendererControl.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using Avalonia;
  2. using Avalonia.Platform;
  3. using Avalonia.Rendering.SceneGraph;
  4. using Avalonia.Skia;
  5. using Avalonia.Threading;
  6. using Ryujinx.Ava.Ui.Backend.Vulkan;
  7. using Ryujinx.Ava.Ui.Vulkan;
  8. using Ryujinx.Common.Configuration;
  9. using Ryujinx.Graphics.Vulkan;
  10. using Silk.NET.Vulkan;
  11. using SkiaSharp;
  12. using SPB.Windowing;
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16. using System.Text;
  17. using System.Threading.Tasks;
  18. namespace Ryujinx.Ava.Ui.Controls
  19. {
  20. internal class VulkanRendererControl : RendererControl
  21. {
  22. private VulkanPlatformInterface _platformInterface;
  23. public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel)
  24. {
  25. _platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
  26. }
  27. public override void DestroyBackgroundContext()
  28. {
  29. }
  30. protected override ICustomDrawOperation CreateDrawOperation()
  31. {
  32. return new VulkanDrawOperation(this);
  33. }
  34. protected override void CreateWindow()
  35. {
  36. }
  37. internal override void MakeCurrent()
  38. {
  39. }
  40. internal override void MakeCurrent(SwappableNativeWindowBase window)
  41. {
  42. }
  43. internal override void Present(object image)
  44. {
  45. Dispatcher.UIThread.InvokeAsync(() =>
  46. {
  47. Image = image;
  48. }).Wait();
  49. QueueRender();
  50. }
  51. private class VulkanDrawOperation : ICustomDrawOperation
  52. {
  53. public Rect Bounds { get; }
  54. private readonly VulkanRendererControl _control;
  55. public VulkanDrawOperation(VulkanRendererControl control)
  56. {
  57. _control = control;
  58. Bounds = _control.Bounds;
  59. }
  60. public void Dispose()
  61. {
  62. }
  63. public bool Equals(ICustomDrawOperation other)
  64. {
  65. return other is VulkanDrawOperation operation && Equals(this, operation) && operation.Bounds == Bounds;
  66. }
  67. public bool HitTest(Point p)
  68. {
  69. return Bounds.Contains(p);
  70. }
  71. public void Render(IDrawingContextImpl context)
  72. {
  73. if (_control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0)
  74. {
  75. return;
  76. }
  77. var image = (PresentImageInfo)_control.Image;
  78. if (context is not ISkiaDrawingContextImpl skiaDrawingContextImpl)
  79. {
  80. return;
  81. }
  82. _control._platformInterface.Device.QueueWaitIdle();
  83. var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
  84. var imageInfo = new GRVkImageInfo()
  85. {
  86. CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex,
  87. Format = (uint)Format.R8G8B8A8Unorm,
  88. Image = image.Image.Handle,
  89. ImageLayout = (uint)ImageLayout.ColorAttachmentOptimal,
  90. ImageTiling = (uint)ImageTiling.Optimal,
  91. ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit
  92. | ImageUsageFlags.ImageUsageTransferSrcBit
  93. | ImageUsageFlags.ImageUsageTransferDstBit),
  94. LevelCount = 1,
  95. SampleCount = 1,
  96. Protected = false,
  97. Alloc = new GRVkAlloc()
  98. {
  99. Memory = image.Memory.Handle,
  100. Flags = 0,
  101. Offset = image.MemoryOffset,
  102. Size = image.MemorySize
  103. }
  104. };
  105. using var backendTexture = new GRBackendRenderTarget(
  106. (int)_control.RenderSize.Width,
  107. (int)_control.RenderSize.Height,
  108. 1,
  109. imageInfo);
  110. using var surface = SKSurface.Create(
  111. gpu.GrContext,
  112. backendTexture,
  113. GRSurfaceOrigin.TopLeft,
  114. SKColorType.Rgba8888);
  115. if (surface == null)
  116. {
  117. return;
  118. }
  119. var rect = new Rect(new Point(), _control.RenderSize);
  120. using var snapshot = surface.Snapshot();
  121. skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(), new SKPaint());
  122. }
  123. }
  124. }
  125. }