| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- using System;
- using Avalonia;
- using Silk.NET.Vulkan;
- namespace Ryujinx.Ava.Ui.Vulkan
- {
- internal class VulkanImage : IDisposable
- {
- private readonly VulkanDevice _device;
- private readonly VulkanPhysicalDevice _physicalDevice;
- private readonly VulkanCommandBufferPool _commandBufferPool;
- private ImageLayout _currentLayout;
- private AccessFlags _currentAccessFlags;
- private ImageUsageFlags _imageUsageFlags { get; }
- private ImageView? _imageView { get; set; }
- private DeviceMemory _imageMemory { get; set; }
- internal Image? InternalHandle { get; private set; }
- internal Format Format { get; }
- internal ImageAspectFlags AspectFlags { get; private set; }
- public ulong Handle => InternalHandle?.Handle ?? 0;
- public ulong ViewHandle => _imageView?.Handle ?? 0;
- public uint UsageFlags => (uint)_imageUsageFlags;
- public ulong MemoryHandle => _imageMemory.Handle;
- public uint MipLevels { get; private set; }
- public PixelSize Size { get; }
- public ulong MemorySize { get; private set; }
- public uint CurrentLayout => (uint)_currentLayout;
- public VulkanImage(
- VulkanDevice device,
- VulkanPhysicalDevice physicalDevice,
- VulkanCommandBufferPool commandBufferPool,
- uint format,
- PixelSize size,
- uint mipLevels = 0)
- {
- _device = device;
- _physicalDevice = physicalDevice;
- _commandBufferPool = commandBufferPool;
- Format = (Format)format;
- Size = size;
- MipLevels = mipLevels;
- _imageUsageFlags =
- ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferDstBit |
- ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageSampledBit;
- Initialize();
- }
- public unsafe void Initialize()
- {
- if (!InternalHandle.HasValue)
- {
- MipLevels = MipLevels != 0 ? MipLevels : (uint)Math.Floor(Math.Log(Math.Max(Size.Width, Size.Height), 2));
- var imageCreateInfo = new ImageCreateInfo
- {
- SType = StructureType.ImageCreateInfo,
- ImageType = ImageType.ImageType2D,
- Format = Format,
- Extent = new Extent3D((uint?)Size.Width, (uint?)Size.Height, 1),
- MipLevels = MipLevels,
- ArrayLayers = 1,
- Samples = SampleCountFlags.SampleCount1Bit,
- Tiling = Tiling,
- Usage = _imageUsageFlags,
- SharingMode = SharingMode.Exclusive,
- InitialLayout = ImageLayout.Undefined,
- Flags = ImageCreateFlags.ImageCreateMutableFormatBit
- };
- _device.Api.CreateImage(_device.InternalHandle, imageCreateInfo, null, out var image).ThrowOnError();
- InternalHandle = image;
- _device.Api.GetImageMemoryRequirements(_device.InternalHandle, InternalHandle.Value,
- out var memoryRequirements);
- var memoryAllocateInfo = new MemoryAllocateInfo
- {
- SType = StructureType.MemoryAllocateInfo,
- AllocationSize = memoryRequirements.Size,
- MemoryTypeIndex = (uint)VulkanMemoryHelper.FindSuitableMemoryTypeIndex(
- _physicalDevice,
- memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit)
- };
- _device.Api.AllocateMemory(_device.InternalHandle, memoryAllocateInfo, null,
- out var imageMemory);
- _imageMemory = imageMemory;
- _device.Api.BindImageMemory(_device.InternalHandle, InternalHandle.Value, _imageMemory, 0);
- MemorySize = memoryRequirements.Size;
- var componentMapping = new ComponentMapping(
- ComponentSwizzle.Identity,
- ComponentSwizzle.Identity,
- ComponentSwizzle.Identity,
- ComponentSwizzle.Identity);
- AspectFlags = ImageAspectFlags.ImageAspectColorBit;
- var subresourceRange = new ImageSubresourceRange(AspectFlags, 0, MipLevels, 0, 1);
- var imageViewCreateInfo = new ImageViewCreateInfo
- {
- SType = StructureType.ImageViewCreateInfo,
- Image = InternalHandle.Value,
- ViewType = ImageViewType.ImageViewType2D,
- Format = Format,
- Components = componentMapping,
- SubresourceRange = subresourceRange
- };
- _device.Api
- .CreateImageView(_device.InternalHandle, imageViewCreateInfo, null, out var imageView)
- .ThrowOnError();
- _imageView = imageView;
- _currentLayout = ImageLayout.Undefined;
- TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
- }
- }
- public ImageTiling Tiling => ImageTiling.Optimal;
- internal void TransitionLayout(ImageLayout destinationLayout, AccessFlags destinationAccessFlags)
- {
- var commandBuffer = _commandBufferPool.CreateCommandBuffer();
- commandBuffer.BeginRecording();
- VulkanMemoryHelper.TransitionLayout(_device, commandBuffer.InternalHandle, InternalHandle.Value,
- _currentLayout,
- _currentAccessFlags,
- destinationLayout, destinationAccessFlags,
- MipLevels);
- commandBuffer.EndRecording();
- commandBuffer.Submit();
- _currentLayout = destinationLayout;
- _currentAccessFlags = destinationAccessFlags;
- }
- public void Dispose()
- {
- if (InternalHandle != null)
- {
- _device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, Span<AllocationCallbacks>.Empty);
- _device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, Span<AllocationCallbacks>.Empty);
- _device.Api.FreeMemory(_device.InternalHandle, _imageMemory, Span<AllocationCallbacks>.Empty);
- _imageView = default;
- InternalHandle = null;
- _imageMemory = default;
- }
- }
- }
- }
|