VulkanImage.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using System;
  2. using Avalonia;
  3. using Silk.NET.Vulkan;
  4. namespace Ryujinx.Ava.Ui.Vulkan
  5. {
  6. internal class VulkanImage : IDisposable
  7. {
  8. private readonly VulkanDevice _device;
  9. private readonly VulkanPhysicalDevice _physicalDevice;
  10. private readonly VulkanCommandBufferPool _commandBufferPool;
  11. private ImageLayout _currentLayout;
  12. private AccessFlags _currentAccessFlags;
  13. private ImageUsageFlags _imageUsageFlags { get; }
  14. private ImageView? _imageView { get; set; }
  15. private DeviceMemory _imageMemory { get; set; }
  16. internal Image? InternalHandle { get; private set; }
  17. internal Format Format { get; }
  18. internal ImageAspectFlags AspectFlags { get; private set; }
  19. public ulong Handle => InternalHandle?.Handle ?? 0;
  20. public ulong ViewHandle => _imageView?.Handle ?? 0;
  21. public uint UsageFlags => (uint)_imageUsageFlags;
  22. public ulong MemoryHandle => _imageMemory.Handle;
  23. public uint MipLevels { get; private set; }
  24. public PixelSize Size { get; }
  25. public ulong MemorySize { get; private set; }
  26. public uint CurrentLayout => (uint)_currentLayout;
  27. public VulkanImage(
  28. VulkanDevice device,
  29. VulkanPhysicalDevice physicalDevice,
  30. VulkanCommandBufferPool commandBufferPool,
  31. uint format,
  32. PixelSize size,
  33. uint mipLevels = 0)
  34. {
  35. _device = device;
  36. _physicalDevice = physicalDevice;
  37. _commandBufferPool = commandBufferPool;
  38. Format = (Format)format;
  39. Size = size;
  40. MipLevels = mipLevels;
  41. _imageUsageFlags =
  42. ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit |
  43. ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageSampledBit;
  44. Initialize();
  45. }
  46. public unsafe void Initialize()
  47. {
  48. if (!InternalHandle.HasValue)
  49. {
  50. MipLevels = MipLevels != 0 ? MipLevels : (uint)Math.Floor(Math.Log(Math.Max(Size.Width, Size.Height), 2));
  51. var imageCreateInfo = new ImageCreateInfo
  52. {
  53. SType = StructureType.ImageCreateInfo,
  54. ImageType = ImageType.ImageType2D,
  55. Format = Format,
  56. Extent = new Extent3D((uint?)Size.Width, (uint?)Size.Height, 1),
  57. MipLevels = MipLevels,
  58. ArrayLayers = 1,
  59. Samples = SampleCountFlags.SampleCount1Bit,
  60. Tiling = Tiling,
  61. Usage = _imageUsageFlags,
  62. SharingMode = SharingMode.Exclusive,
  63. InitialLayout = ImageLayout.Undefined,
  64. Flags = ImageCreateFlags.ImageCreateMutableFormatBit
  65. };
  66. _device.Api.CreateImage(_device.InternalHandle, imageCreateInfo, null, out var image).ThrowOnError();
  67. InternalHandle = image;
  68. _device.Api.GetImageMemoryRequirements(_device.InternalHandle, InternalHandle.Value,
  69. out var memoryRequirements);
  70. var memoryAllocateInfo = new MemoryAllocateInfo
  71. {
  72. SType = StructureType.MemoryAllocateInfo,
  73. AllocationSize = memoryRequirements.Size,
  74. MemoryTypeIndex = (uint)VulkanMemoryHelper.FindSuitableMemoryTypeIndex(
  75. _physicalDevice,
  76. memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit)
  77. };
  78. _device.Api.AllocateMemory(_device.InternalHandle, memoryAllocateInfo, null,
  79. out var imageMemory);
  80. _imageMemory = imageMemory;
  81. _device.Api.BindImageMemory(_device.InternalHandle, InternalHandle.Value, _imageMemory, 0);
  82. MemorySize = memoryRequirements.Size;
  83. var componentMapping = new ComponentMapping(
  84. ComponentSwizzle.Identity,
  85. ComponentSwizzle.Identity,
  86. ComponentSwizzle.Identity,
  87. ComponentSwizzle.Identity);
  88. AspectFlags = ImageAspectFlags.ImageAspectColorBit;
  89. var subresourceRange = new ImageSubresourceRange(AspectFlags, 0, MipLevels, 0, 1);
  90. var imageViewCreateInfo = new ImageViewCreateInfo
  91. {
  92. SType = StructureType.ImageViewCreateInfo,
  93. Image = InternalHandle.Value,
  94. ViewType = ImageViewType.ImageViewType2D,
  95. Format = Format,
  96. Components = componentMapping,
  97. SubresourceRange = subresourceRange
  98. };
  99. _device.Api
  100. .CreateImageView(_device.InternalHandle, imageViewCreateInfo, null, out var imageView)
  101. .ThrowOnError();
  102. _imageView = imageView;
  103. _currentLayout = ImageLayout.Undefined;
  104. TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
  105. }
  106. }
  107. public ImageTiling Tiling => ImageTiling.Optimal;
  108. internal void TransitionLayout(ImageLayout destinationLayout, AccessFlags destinationAccessFlags)
  109. {
  110. var commandBuffer = _commandBufferPool.CreateCommandBuffer();
  111. commandBuffer.BeginRecording();
  112. VulkanMemoryHelper.TransitionLayout(_device, commandBuffer.InternalHandle, InternalHandle.Value,
  113. _currentLayout,
  114. _currentAccessFlags,
  115. destinationLayout, destinationAccessFlags,
  116. MipLevels);
  117. commandBuffer.EndRecording();
  118. commandBuffer.Submit();
  119. _currentLayout = destinationLayout;
  120. _currentAccessFlags = destinationAccessFlags;
  121. }
  122. public void Dispose()
  123. {
  124. if (InternalHandle != null)
  125. {
  126. _device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, Span<AllocationCallbacks>.Empty);
  127. _device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, Span<AllocationCallbacks>.Empty);
  128. _device.Api.FreeMemory(_device.InternalHandle, _imageMemory, Span<AllocationCallbacks>.Empty);
  129. _imageView = default;
  130. InternalHandle = null;
  131. _imageMemory = default;
  132. }
  133. }
  134. }
  135. }