VulkanRenderTarget.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using System;
  2. using Avalonia.Skia;
  3. using Ryujinx.Ava.Ui.Vulkan;
  4. using Ryujinx.Ava.Ui.Vulkan.Surfaces;
  5. using SkiaSharp;
  6. namespace Ryujinx.Ava.Ui.Backend.Vulkan
  7. {
  8. internal class VulkanRenderTarget : ISkiaGpuRenderTarget
  9. {
  10. public GRContext GrContext { get; set; }
  11. private readonly VulkanSurfaceRenderTarget _surface;
  12. private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
  13. public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
  14. {
  15. _surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
  16. _vulkanPlatformSurface = vulkanPlatformSurface;
  17. }
  18. public void Dispose()
  19. {
  20. _surface.Dispose();
  21. }
  22. public ISkiaGpuRenderSession BeginRenderingSession()
  23. {
  24. var session = _surface.BeginDraw(_vulkanPlatformSurface.Scaling);
  25. bool success = false;
  26. try
  27. {
  28. var disp = session.Display;
  29. var api = session.Api;
  30. var size = session.Size;
  31. var scaling = session.Scaling;
  32. if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
  33. {
  34. size = new Avalonia.PixelSize(1, 1);
  35. scaling = 1;
  36. }
  37. lock (GrContext)
  38. {
  39. GrContext.ResetContext();
  40. var imageInfo = new GRVkImageInfo()
  41. {
  42. CurrentQueueFamily = disp.QueueFamilyIndex,
  43. Format = _surface.ImageFormat,
  44. Image = _surface.Image.Handle,
  45. ImageLayout = (uint)_surface.Image.CurrentLayout,
  46. ImageTiling = (uint)_surface.Image.Tiling,
  47. ImageUsageFlags = _surface.UsageFlags,
  48. LevelCount = _surface.MipLevels,
  49. SampleCount = 1,
  50. Protected = false,
  51. Alloc = new GRVkAlloc()
  52. {
  53. Memory = _surface.Image.MemoryHandle,
  54. Flags = 0,
  55. Offset = 0,
  56. Size = _surface.MemorySize
  57. }
  58. };
  59. var renderTarget =
  60. new GRBackendRenderTarget((int)size.Width, (int)size.Height, 1,
  61. imageInfo);
  62. var surface = SKSurface.Create(GrContext, renderTarget,
  63. GRSurfaceOrigin.TopLeft,
  64. _surface.IsRgba ? SKColorType.Rgba8888 : SKColorType.Bgra8888, SKColorSpace.CreateSrgb());
  65. if (surface == null)
  66. {
  67. throw new InvalidOperationException(
  68. "Surface can't be created with the provided render target");
  69. }
  70. success = true;
  71. return new VulkanGpuSession(GrContext, renderTarget, surface, session);
  72. }
  73. }
  74. finally
  75. {
  76. if (!success)
  77. {
  78. session.Dispose();
  79. }
  80. }
  81. }
  82. public bool IsCorrupted { get; }
  83. internal class VulkanGpuSession : ISkiaGpuRenderSession
  84. {
  85. private readonly GRBackendRenderTarget _backendRenderTarget;
  86. private readonly VulkanSurfaceRenderingSession _vulkanSession;
  87. public VulkanGpuSession(GRContext grContext,
  88. GRBackendRenderTarget backendRenderTarget,
  89. SKSurface surface,
  90. VulkanSurfaceRenderingSession vulkanSession)
  91. {
  92. GrContext = grContext;
  93. _backendRenderTarget = backendRenderTarget;
  94. SkSurface = surface;
  95. _vulkanSession = vulkanSession;
  96. SurfaceOrigin = GRSurfaceOrigin.TopLeft;
  97. }
  98. public void Dispose()
  99. {
  100. lock (_vulkanSession.Display.Lock)
  101. {
  102. SkSurface.Canvas.Flush();
  103. SkSurface.Dispose();
  104. _backendRenderTarget.Dispose();
  105. GrContext.Flush();
  106. _vulkanSession.Dispose();
  107. }
  108. }
  109. public GRContext GrContext { get; }
  110. public SKSurface SkSurface { get; }
  111. public double ScaleFactor => _vulkanSession.Scaling;
  112. public GRSurfaceOrigin SurfaceOrigin { get; }
  113. }
  114. }
  115. }