forked from amkovkov/GranuSightSoftware2
feat: GSS2.Test Vulkan render image
This commit is contained in:
+263
-124
@@ -9,16 +9,13 @@ using Avalonia.Threading;
|
|||||||
|
|
||||||
using GSS2.Vulkan;
|
using GSS2.Vulkan;
|
||||||
|
|
||||||
using Iot.Device.FtCommon;
|
|
||||||
|
|
||||||
using LibCameraSharp;
|
using LibCameraSharp;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
|
||||||
|
|
||||||
using Silk.NET.Core;
|
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using Silk.NET.Vulkan.Extensions.KHR;
|
using Silk.NET.Vulkan.Extensions.KHR;
|
||||||
|
|
||||||
|
using Image = Silk.NET.Vulkan.Image;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test;
|
||||||
|
|
||||||
interface IImage
|
interface IImage
|
||||||
@@ -46,7 +43,7 @@ class VkImage
|
|||||||
{
|
{
|
||||||
Width = Width,
|
Width = Width,
|
||||||
Height = Height,
|
Height = Height,
|
||||||
Format = PlatformGraphicsExternalImageFormat.R8G8B8A8UNorm,
|
Format = PlatformGraphicsExternalImageFormat.B8G8R8A8UNorm,
|
||||||
MemorySize = MemorySize
|
MemorySize = MemorySize
|
||||||
},
|
},
|
||||||
Semaphore
|
Semaphore
|
||||||
@@ -63,66 +60,22 @@ class VkRenderer
|
|||||||
return new PlatformHandle(new IntPtr(fd), KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
|
return new PlatformHandle(new IntPtr(fd), KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaquePosixFileDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe public VkImage ImportOrUpdate(int fd, int width, int height)
|
unsafe public VkImage ImportOrUpdate(int fd, int width, int height, int stride)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var extImageInfo = new ExternalMemoryImageCreateInfo
|
var (importImage, importMemoryReqirements, importMemory) = ImportImage(fd, width, height, stride);
|
||||||
{
|
var (exportImage, exportMemoryReqirements, exportMemory) = CreateExportImage(width, height);
|
||||||
SType = StructureType.ExternalMemoryImageCreateInfo,
|
|
||||||
HandleTypes = ExternalMemoryHandleTypeFlags.OpaqueFDBit
|
|
||||||
};
|
|
||||||
|
|
||||||
var imageInfo = new ImageCreateInfo
|
var commandPoolCreateInfo = new CommandPoolCreateInfo
|
||||||
{
|
|
||||||
SType = StructureType.ImageCreateInfo,
|
|
||||||
PNext = &extImageInfo,
|
|
||||||
ImageType = ImageType.Type2D,
|
|
||||||
Format = Format.R8G8B8A8Unorm,
|
|
||||||
Extent = new Extent3D
|
|
||||||
{
|
|
||||||
Width = checked((uint)width),
|
|
||||||
Height = checked((uint)height),
|
|
||||||
Depth = 1
|
|
||||||
},
|
|
||||||
MipLevels = 1,
|
|
||||||
ArrayLayers = 1,
|
|
||||||
Samples = SampleCountFlags.Count1Bit,
|
|
||||||
Tiling = ImageTiling.Optimal,
|
|
||||||
Usage = ImageUsageFlags.TransferDstBit | ImageUsageFlags.SampledBit,
|
|
||||||
SharingMode = SharingMode.Exclusive,
|
|
||||||
InitialLayout = ImageLayout.Undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
context.Api.CreateImage(context.Device, &imageInfo, null, out var image).ThrowOnError();
|
|
||||||
context.Api.GetImageMemoryRequirements(context.Device, image, out var memReq);
|
|
||||||
|
|
||||||
var exportAllocInfo = new ExportMemoryAllocateInfo
|
|
||||||
{
|
|
||||||
SType = StructureType.ExportMemoryAllocateInfo,
|
|
||||||
HandleTypes = ExternalMemoryHandleTypeFlags.OpaqueFDBit
|
|
||||||
};
|
|
||||||
|
|
||||||
var allocInfo = new MemoryAllocateInfo
|
|
||||||
{
|
|
||||||
SType = StructureType.MemoryAllocateInfo,
|
|
||||||
PNext = &exportAllocInfo,
|
|
||||||
AllocationSize = memReq.Size,
|
|
||||||
MemoryTypeIndex = checked((uint)FindMemoryType(memReq.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit))
|
|
||||||
};
|
|
||||||
|
|
||||||
context.Api.AllocateMemory(context.Device, &allocInfo, null, out var memory).ThrowOnError();
|
|
||||||
context.Api.BindImageMemory(context.Device, image, memory, 0).ThrowOnError();
|
|
||||||
|
|
||||||
var poolInfo = new CommandPoolCreateInfo
|
|
||||||
{
|
{
|
||||||
SType = StructureType.CommandPoolCreateInfo,
|
SType = StructureType.CommandPoolCreateInfo,
|
||||||
Flags = CommandPoolCreateFlags.ResetCommandBufferBit,
|
Flags = CommandPoolCreateFlags.ResetCommandBufferBit,
|
||||||
QueueFamilyIndex = context.QueueFamilyIndex
|
QueueFamilyIndex = context.QueueFamilyIndex
|
||||||
};
|
};
|
||||||
context.Api.CreateCommandPool(context.Device, &poolInfo, null, out var commandPool).ThrowOnError();
|
context.Api.CreateCommandPool(context.Device, &commandPoolCreateInfo, null, out var commandPool).ThrowOnError();
|
||||||
|
|
||||||
var cmdBufferAllocInfo = new CommandBufferAllocateInfo
|
var commandBufferAllocateInfo = new CommandBufferAllocateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.CommandBufferAllocateInfo,
|
SType = StructureType.CommandBufferAllocateInfo,
|
||||||
CommandPool = commandPool,
|
CommandPool = commandPool,
|
||||||
@@ -130,65 +83,75 @@ class VkRenderer
|
|||||||
CommandBufferCount = 1
|
CommandBufferCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
context.Api.AllocateCommandBuffers(context.Device, &cmdBufferAllocInfo, out var cmd).ThrowOnError();
|
context.Api.AllocateCommandBuffers(context.Device, &commandBufferAllocateInfo, out var commandBuffers).ThrowOnError();
|
||||||
|
|
||||||
var clearColor = new ClearColorValue((float)Random.Shared.NextDouble(), (float)Random.Shared.NextDouble(), (float)Random.Shared.NextDouble(), (float)Random.Shared.NextDouble());
|
var commandBufferBeginInfo = new CommandBufferBeginInfo
|
||||||
var range = new ImageSubresourceRange
|
|
||||||
{
|
|
||||||
AspectMask = ImageAspectFlags.ColorBit,
|
|
||||||
BaseMipLevel = 0,
|
|
||||||
LevelCount = 1,
|
|
||||||
BaseArrayLayer = 0,
|
|
||||||
LayerCount = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
var beginInfo = new CommandBufferBeginInfo
|
|
||||||
{
|
{
|
||||||
SType = StructureType.CommandBufferBeginInfo,
|
SType = StructureType.CommandBufferBeginInfo,
|
||||||
Flags = CommandBufferUsageFlags.OneTimeSubmitBit
|
Flags = CommandBufferUsageFlags.OneTimeSubmitBit
|
||||||
};
|
};
|
||||||
context.Api.BeginCommandBuffer(cmd, &beginInfo).ThrowOnError();
|
context.Api.BeginCommandBuffer(commandBuffers, &commandBufferBeginInfo).ThrowOnError();
|
||||||
|
|
||||||
TransitionImageLayout(cmd, image, ImageLayout.Undefined, ImageLayout.TransferDstOptimal);
|
TransitionImageLayout(commandBuffers, importImage, ImageLayout.Undefined, ImageLayout.TransferSrcOptimal);
|
||||||
|
TransitionImageLayout(commandBuffers, exportImage, ImageLayout.Undefined, ImageLayout.TransferDstOptimal);
|
||||||
|
|
||||||
context.Api.CmdClearColorImage(cmd, image, ImageLayout.TransferDstOptimal, &clearColor, 1, &range);
|
var region = new ImageCopy
|
||||||
|
{
|
||||||
|
SrcSubresource = new ImageSubresourceLayers
|
||||||
|
{
|
||||||
|
AspectMask = ImageAspectFlags.ColorBit,
|
||||||
|
MipLevel = 0,
|
||||||
|
BaseArrayLayer = 0,
|
||||||
|
LayerCount = 1
|
||||||
|
},
|
||||||
|
SrcOffset = new Offset3D(0, 0, 0),
|
||||||
|
DstSubresource = new ImageSubresourceLayers
|
||||||
|
{
|
||||||
|
AspectMask = ImageAspectFlags.ColorBit,
|
||||||
|
MipLevel = 0,
|
||||||
|
BaseArrayLayer = 0,
|
||||||
|
LayerCount = 1
|
||||||
|
},
|
||||||
|
DstOffset = new Offset3D(0, 0, 0),
|
||||||
|
Extent = new Extent3D((uint)width, (uint)height, 1)
|
||||||
|
};
|
||||||
|
context.Api.CmdCopyImage(commandBuffers, importImage, ImageLayout.Undefined, exportImage, ImageLayout.Undefined, [region]);
|
||||||
|
|
||||||
TransitionImageLayout(cmd, image, ImageLayout.TransferDstOptimal, ImageLayout.General);
|
TransitionImageLayout(commandBuffers, exportImage, ImageLayout.TransferDstOptimal, ImageLayout.General);
|
||||||
|
|
||||||
context.Api.EndCommandBuffer(cmd).ThrowOnError();
|
context.Api.EndCommandBuffer(commandBuffers).ThrowOnError();
|
||||||
|
|
||||||
|
if (context.Api.TryGetDeviceExtension<KhrExternalMemoryFd>(context.Instance, context.Device, out var khrExternalMemoryFd))
|
||||||
|
Console.WriteLine("KhrExternalMemoryFd import success");
|
||||||
|
else
|
||||||
|
throw new Exception("KhrExternalMemoryFd import error");
|
||||||
|
var MemoryGetFdInfoKHR = new MemoryGetFdInfoKHR
|
||||||
|
{
|
||||||
|
SType = StructureType.MemoryGetFDInfoKhr,
|
||||||
|
Memory = exportMemory,
|
||||||
|
HandleType = ExternalMemoryHandleTypeFlags.OpaqueFDBit
|
||||||
|
};
|
||||||
|
khrExternalMemoryFd.GetMemoryF(context.Device, &MemoryGetFdInfoKHR, out var vulkanFd).ThrowOnError();
|
||||||
|
Console.WriteLine($"Image export success {vulkanFd}");
|
||||||
|
|
||||||
var renderFinished = context.RenderFinishedSemaphore;
|
var renderFinished = context.RenderFinishedSemaphore;
|
||||||
|
|
||||||
var submitInfo = new SubmitInfo
|
var submitInfo = new SubmitInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.SubmitInfo,
|
SType = StructureType.SubmitInfo,
|
||||||
CommandBufferCount = 1,
|
CommandBufferCount = 1,
|
||||||
PCommandBuffers = &cmd,
|
PCommandBuffers = &commandBuffers,
|
||||||
PSignalSemaphores = &renderFinished,
|
PSignalSemaphores = &renderFinished,
|
||||||
SignalSemaphoreCount = 1
|
SignalSemaphoreCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
context.Api.QueueSubmit(context.Queue, 1, &submitInfo, default).ThrowOnError();
|
context.Api.QueueSubmit(context.Queue, 1, &submitInfo, default).ThrowOnError();
|
||||||
|
|
||||||
var getFdInfo = new MemoryGetFdInfoKHR
|
|
||||||
{
|
|
||||||
SType = StructureType.MemoryGetFDInfoKhr,
|
|
||||||
Memory = memory,
|
|
||||||
HandleType = ExternalMemoryHandleTypeFlags.OpaqueFDBit
|
|
||||||
};
|
|
||||||
if (context.Api.TryGetDeviceExtension<KhrExternalMemoryFd>(context.Instance, context.Device, out var khrExternalMemoryFd))
|
|
||||||
Console.WriteLine("KhrExternalMemoryFd import success");
|
|
||||||
else
|
|
||||||
throw new Exception("KhrExternalMemoryFd import error");
|
|
||||||
khrExternalMemoryFd.GetMemoryF(context.Device, &getFdInfo, out var fd1).ThrowOnError();
|
|
||||||
Console.WriteLine($"Image export success {fd1}");
|
|
||||||
|
|
||||||
return new VkImage()
|
return new VkImage()
|
||||||
{
|
{
|
||||||
Width = width,
|
Width = width,
|
||||||
Height = height,
|
Height = height,
|
||||||
Fd = fd1,
|
Fd = vulkanFd,
|
||||||
MemorySize = memReq.Size
|
MemorySize = exportMemoryReqirements.Size
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -199,6 +162,109 @@ class VkRenderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe public (Image, MemoryRequirements, DeviceMemory) ImportImage(int fd, int width, int height, int stride)
|
||||||
|
{
|
||||||
|
var subresourceLayout = new SubresourceLayout
|
||||||
|
{
|
||||||
|
Offset = 0,
|
||||||
|
RowPitch = checked((ulong)stride),
|
||||||
|
};
|
||||||
|
var imageDrmFormatModifierExplicitCreateInfoEXT = new ImageDrmFormatModifierExplicitCreateInfoEXT
|
||||||
|
{
|
||||||
|
SType = StructureType.ImageDrmFormatModifierExplicitCreateInfoExt,
|
||||||
|
DrmFormatModifier = 0,
|
||||||
|
DrmFormatModifierPlaneCount = 1,
|
||||||
|
PPlaneLayouts = &subresourceLayout,
|
||||||
|
};
|
||||||
|
var imageCreateInfo = new ImageCreateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.ImageCreateInfo,
|
||||||
|
PNext = &imageDrmFormatModifierExplicitCreateInfoEXT,
|
||||||
|
ImageType = ImageType.Type2D,
|
||||||
|
Format = Format.B8G8R8A8Unorm,
|
||||||
|
Extent = new Extent3D
|
||||||
|
{
|
||||||
|
Width = checked((uint)width),
|
||||||
|
Height = checked((uint)height),
|
||||||
|
Depth = 1
|
||||||
|
},
|
||||||
|
MipLevels = 1,
|
||||||
|
ArrayLayers = 1,
|
||||||
|
Samples = SampleCountFlags.Count1Bit,
|
||||||
|
Tiling = ImageTiling.DrmFormatModifierExt,
|
||||||
|
Usage = ImageUsageFlags.TransferSrcBit | ImageUsageFlags.SampledBit,
|
||||||
|
SharingMode = SharingMode.Exclusive,
|
||||||
|
InitialLayout = ImageLayout.Undefined,
|
||||||
|
};
|
||||||
|
context.Api.CreateImage(context.Device, &imageCreateInfo, null, out var image).ThrowOnError();
|
||||||
|
context.Api.GetImageMemoryRequirements(context.Device, image, out var memoryReqirements);
|
||||||
|
|
||||||
|
var importMemoryFdInfoKHR = new ImportMemoryFdInfoKHR
|
||||||
|
{
|
||||||
|
SType = StructureType.ImportMemoryFDInfoKhr,
|
||||||
|
HandleType = ExternalMemoryHandleTypeFlags.DmaBufBitExt,
|
||||||
|
Fd = fd,
|
||||||
|
};
|
||||||
|
var memoryAllocateInfo = new MemoryAllocateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.MemoryAllocateInfo,
|
||||||
|
AllocationSize = memoryReqirements.Size,
|
||||||
|
MemoryTypeIndex = checked((uint)FindMemoryType(memoryReqirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)),
|
||||||
|
PNext = &importMemoryFdInfoKHR,
|
||||||
|
};
|
||||||
|
context.Api.AllocateMemory(context.Device, &memoryAllocateInfo, null, out var memory).ThrowOnError();
|
||||||
|
context.Api.BindImageMemory(context.Device, image, memory, 0).ThrowOnError();
|
||||||
|
|
||||||
|
return (image, memoryReqirements, memory);
|
||||||
|
}
|
||||||
|
unsafe public (Image, MemoryRequirements, DeviceMemory) CreateExportImage(int width, int height)
|
||||||
|
{
|
||||||
|
var externalMemoryImageCreateInfo = new ExternalMemoryImageCreateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.ExternalMemoryImageCreateInfo,
|
||||||
|
HandleTypes = ExternalMemoryHandleTypeFlags.OpaqueFDBit
|
||||||
|
};
|
||||||
|
var imageCreateInfo = new ImageCreateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.ImageCreateInfo,
|
||||||
|
PNext = &externalMemoryImageCreateInfo,
|
||||||
|
ImageType = ImageType.Type2D,
|
||||||
|
Format = Format.B8G8R8A8Unorm,
|
||||||
|
Extent = new Extent3D
|
||||||
|
{
|
||||||
|
Width = checked((uint)width),
|
||||||
|
Height = checked((uint)height),
|
||||||
|
Depth = 1
|
||||||
|
},
|
||||||
|
MipLevels = 1,
|
||||||
|
ArrayLayers = 1,
|
||||||
|
Samples = SampleCountFlags.Count1Bit,
|
||||||
|
Tiling = ImageTiling.Optimal,
|
||||||
|
Usage = ImageUsageFlags.TransferDstBit | ImageUsageFlags.SampledBit,
|
||||||
|
SharingMode = SharingMode.Exclusive,
|
||||||
|
InitialLayout = ImageLayout.Undefined,
|
||||||
|
};
|
||||||
|
context.Api.CreateImage(context.Device, &imageCreateInfo, null, out var image).ThrowOnError();
|
||||||
|
context.Api.GetImageMemoryRequirements(context.Device, image, out var memoryReqirements);
|
||||||
|
|
||||||
|
var exportMemoryFdInfoKHR = new ExportMemoryAllocateInfoKHR
|
||||||
|
{
|
||||||
|
SType = StructureType.ExportMemoryAllocateInfoKhr,
|
||||||
|
HandleTypes = ExternalMemoryHandleTypeFlags.DmaBufBitExt
|
||||||
|
};
|
||||||
|
var exportAllocateInfo = new MemoryAllocateInfo
|
||||||
|
{
|
||||||
|
SType = StructureType.MemoryAllocateInfo,
|
||||||
|
AllocationSize = memoryReqirements.Size,
|
||||||
|
MemoryTypeIndex = checked((uint)FindMemoryType(memoryReqirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)),
|
||||||
|
PNext = &exportMemoryFdInfoKHR,
|
||||||
|
};
|
||||||
|
context.Api.AllocateMemory(context.Device, &exportAllocateInfo, null, out var memory).ThrowOnError();
|
||||||
|
context.Api.BindImageMemory(context.Device, image, memory, 0).ThrowOnError();
|
||||||
|
|
||||||
|
return (image, memoryReqirements, memory);
|
||||||
|
}
|
||||||
|
|
||||||
private int FindMemoryType(uint typeFilter, MemoryPropertyFlags properties)
|
private int FindMemoryType(uint typeFilter, MemoryPropertyFlags properties)
|
||||||
{
|
{
|
||||||
context!.Api.GetPhysicalDeviceMemoryProperties(context.PhysicalDevice, out var memProps);
|
context!.Api.GetPhysicalDeviceMemoryProperties(context.PhysicalDevice, out var memProps);
|
||||||
@@ -207,15 +273,15 @@ class VkRenderer
|
|||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
unsafe private void TransitionImageLayout(CommandBuffer cmd, Silk.NET.Vulkan.Image image, ImageLayout oldLayout, ImageLayout newLayout)
|
unsafe private void TransitionImageLayout(CommandBuffer cmd, Image image, ImageLayout oldLayout, ImageLayout newLayout)
|
||||||
{
|
{
|
||||||
var barrier = new ImageMemoryBarrier
|
var barrier = new ImageMemoryBarrier
|
||||||
{
|
{
|
||||||
SType = StructureType.ImageMemoryBarrier,
|
SType = StructureType.ImageMemoryBarrier,
|
||||||
OldLayout = oldLayout,
|
OldLayout = oldLayout,
|
||||||
NewLayout = newLayout,
|
NewLayout = newLayout,
|
||||||
SrcQueueFamilyIndex = 0,
|
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||||
DstQueueFamilyIndex = 0,
|
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||||
Image = image,
|
Image = image,
|
||||||
SubresourceRange = new ImageSubresourceRange
|
SubresourceRange = new ImageSubresourceRange
|
||||||
{
|
{
|
||||||
@@ -227,37 +293,70 @@ class VkRenderer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PipelineStageFlags srcStage;
|
context.Api.CmdPipelineBarrier(
|
||||||
PipelineStageFlags dstStage;
|
cmd,
|
||||||
|
PipelineStageFlags.TopOfPipeBit,
|
||||||
if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.TransferDstOptimal)
|
PipelineStageFlags.TransferBit,
|
||||||
{
|
0,
|
||||||
barrier.SrcAccessMask = 0;
|
0, null,
|
||||||
barrier.DstAccessMask = AccessFlags.TransferWriteBit;
|
0, null,
|
||||||
|
1, &barrier);
|
||||||
srcStage = PipelineStageFlags.TopOfPipeBit;
|
|
||||||
dstStage = PipelineStageFlags.TransferBit;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (oldLayout == ImageLayout.TransferDstOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal)
|
|
||||||
{
|
|
||||||
|
|
||||||
barrier.SrcAccessMask = AccessFlags.TransferWriteBit;
|
|
||||||
barrier.DstAccessMask = AccessFlags.ShaderReadBit;
|
|
||||||
|
|
||||||
srcStage = PipelineStageFlags.TransferBit;
|
|
||||||
dstStage = PipelineStageFlags.FragmentShaderBit;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
srcStage = PipelineStageFlags.AllCommandsBit;
|
|
||||||
dstStage = PipelineStageFlags.AllCommandsBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
context!.Api.CmdPipelineBarrier(cmd, srcStage, dstStage, 0, 0, null, 0, null, 1, &barrier);
|
|
||||||
}
|
}
|
||||||
|
// unsafe private void TransitionImageLayout(CommandBuffer cmd, Silk.NET.Vulkan.Image image, ImageLayout oldLayout, ImageLayout newLayout)
|
||||||
|
// {
|
||||||
|
// var barrier = new ImageMemoryBarrier
|
||||||
|
// {
|
||||||
|
// SType = StructureType.ImageMemoryBarrier,
|
||||||
|
// OldLayout = oldLayout,
|
||||||
|
// NewLayout = newLayout,
|
||||||
|
// SrcQueueFamilyIndex = 0,
|
||||||
|
// DstQueueFamilyIndex = 0,
|
||||||
|
// Image = image,
|
||||||
|
// SubresourceRange = new ImageSubresourceRange
|
||||||
|
// {
|
||||||
|
// AspectMask = ImageAspectFlags.ColorBit,
|
||||||
|
// BaseMipLevel = 0,
|
||||||
|
// LevelCount = 1,
|
||||||
|
// BaseArrayLayer = 0,
|
||||||
|
// LayerCount = 1
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// PipelineStageFlags srcStage;
|
||||||
|
// PipelineStageFlags dstStage;
|
||||||
|
|
||||||
|
// if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.TransferDstOptimal)
|
||||||
|
// {
|
||||||
|
// barrier.SrcAccessMask = 0;
|
||||||
|
// barrier.DstAccessMask = AccessFlags.TransferWriteBit;
|
||||||
|
|
||||||
|
// srcStage = PipelineStageFlags.TopOfPipeBit;
|
||||||
|
// dstStage = PipelineStageFlags.TransferBit;
|
||||||
|
// }
|
||||||
|
// else if (oldLayout == ImageLayout.Undefined && newLayout == ImageLayout.ShaderReadOnlyOptimal)
|
||||||
|
// {
|
||||||
|
// barrier.SrcAccessMask = 0;
|
||||||
|
// barrier.DstAccessMask = AccessFlags.ShaderReadBit;
|
||||||
|
|
||||||
|
// srcStage = PipelineStageFlags.TopOfPipeBit;
|
||||||
|
// dstStage = PipelineStageFlags.FragmentShaderBit;
|
||||||
|
// }
|
||||||
|
// else if (oldLayout == ImageLayout.TransferDstOptimal && newLayout == ImageLayout.ShaderReadOnlyOptimal)
|
||||||
|
// {
|
||||||
|
// barrier.SrcAccessMask = AccessFlags.TransferWriteBit;
|
||||||
|
// barrier.DstAccessMask = AccessFlags.ShaderReadBit;
|
||||||
|
|
||||||
|
// srcStage = PipelineStageFlags.TransferBit;
|
||||||
|
// dstStage = PipelineStageFlags.FragmentShaderBit;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// srcStage = PipelineStageFlags.AllCommandsBit;
|
||||||
|
// dstStage = PipelineStageFlags.AllCommandsBit;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// context!.Api.CmdPipelineBarrier(cmd, srcStage, dstStage, 0, 0, null, 0, null, 1, &barrier);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class CameraView : Control
|
public partial class CameraView : Control
|
||||||
@@ -327,16 +426,56 @@ public partial class CameraView : Control
|
|||||||
var (handle, properties, semaphore) = image.Export();
|
var (handle, properties, semaphore) = image.Export();
|
||||||
|
|
||||||
var imageRenderedSemaphore = _gpuInterop!.ImportSemaphore(_renerer!.ExportSemaphore(false));
|
var imageRenderedSemaphore = _gpuInterop!.ImportSemaphore(_renerer!.ExportSemaphore(false));
|
||||||
|
imageRenderedSemaphore.ImportCompleted.ContinueWith(t =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"imageRenderedSemaphore.ImportCompleted {t.Status}");
|
||||||
|
if (t.Exception is not null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: \n{t.Exception.Message}\n{t.Exception.StackTrace} ");
|
||||||
|
foreach (var e in t.Exception.InnerExceptions)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
Console.WriteLine(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
var renderCompletedSemaphore = _gpuInterop!.ImportSemaphore(_renerer!.ExportSemaphore(true));
|
var renderCompletedSemaphore = _gpuInterop!.ImportSemaphore(_renerer!.ExportSemaphore(true));
|
||||||
|
renderCompletedSemaphore.ImportCompleted.ContinueWith(t =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"renderCompletedSemaphore.ImportCompleted {t.Status}");
|
||||||
|
if (t.Exception is not null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: \n{t.Exception.Message}\n{t.Exception.StackTrace} ");
|
||||||
|
foreach (var e in t.Exception.InnerExceptions)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
Console.WriteLine(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Console.WriteLine("ImportImage");
|
||||||
var importedImage = _gpuInterop!.ImportImage(handle, properties);
|
var importedImage = _gpuInterop!.ImportImage(handle, properties);
|
||||||
|
importedImage.ImportCompleted.ContinueWith(t =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"importedImage.ImportCompleted {t.Status}");
|
||||||
|
if (t.Exception is not null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error: \n{t.Exception.Message}\n{t.Exception.StackTrace} ");
|
||||||
|
foreach (var e in t.Exception.InnerExceptions)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.Message);
|
||||||
|
Console.WriteLine(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Dispatcher.UIThread.Invoke(async () =>
|
Dispatcher.UIThread.Invoke(async () =>
|
||||||
{
|
{
|
||||||
await importedImage.ImportCompleted;
|
|
||||||
await Surface!.UpdateWithSemaphoresAsync(importedImage, renderCompletedSemaphore, imageRenderedSemaphore)
|
await Surface!.UpdateWithSemaphoresAsync(importedImage, renderCompletedSemaphore, imageRenderedSemaphore)
|
||||||
.ContinueWith((t) =>
|
.ContinueWith((t) =>
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"UpdateWithSemaphoresAsync {t.Status}");
|
||||||
if (t.Exception is not null)
|
if (t.Exception is not null)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error while surface update: \n{t.Exception.Message}\n{t.Exception.StackTrace} ");
|
Console.WriteLine($"Error while surface update: \n{t.Exception.Message}\n{t.Exception.StackTrace} ");
|
||||||
@@ -367,7 +506,7 @@ public partial class CameraView : Control
|
|||||||
|
|
||||||
if (frameBuffer is not null && streamConfiguration is not null && _renerer is not null)
|
if (frameBuffer is not null && streamConfiguration is not null && _renerer is not null)
|
||||||
{
|
{
|
||||||
var image = _renerer.ImportOrUpdate(frameBuffer.Planes.First().Fd.Get(), checked((int)streamConfiguration.Size.Width), checked((int)streamConfiguration.Size.Height));
|
var image = _renerer.ImportOrUpdate(frameBuffer.Planes.First().Fd.Get(), checked((int)streamConfiguration.Size.Width), checked((int)streamConfiguration.Size.Height), checked((int)streamConfiguration.Stride));
|
||||||
_latestImage = image;
|
_latestImage = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
// Основан на примере GpuInterop Avalonia
|
// Основан на примере GpuInterop Avalonia
|
||||||
// https://github.com/AvaloniaUI/Avalonia/blob/5f3dbae22244e830b464fc680c6c28ca124be41a/samples/GpuInterop/VulkanDemo/VulkanExtensions.cs
|
// https://github.com/AvaloniaUI/Avalonia/blob/5f3dbae22244e830b464fc680c6c28ca124be41a/samples/GpuInterop/VulkanDemo/VulkanExtensions.cs
|
||||||
|
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
|
|
||||||
namespace GSS2.Vulkan;
|
namespace GSS2.Vulkan;
|
||||||
|
|
||||||
public static class VulkanExtensions
|
public static class VulkanExtensions
|
||||||
{
|
{
|
||||||
public static void ThrowOnError(this Result result)
|
public static void ThrowOnError(this Result result, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = -1)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"{callerFilePath} {callerMemberName} {callerLineNumber} {result}");
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
throw new Exception($"Unexpected API error \"{result}\"");
|
throw new Exception($"Unexpected API error \"{result}\"");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user