diff --git a/GSS2.Core/GSS2.Core.csproj b/GSS2.Core/GSS2.Core.csproj
index 061e878..3298c1f 100644
--- a/GSS2.Core/GSS2.Core.csproj
+++ b/GSS2.Core/GSS2.Core.csproj
@@ -21,7 +21,7 @@
-
+
diff --git a/GSS2.Core/Hardware/CameraService.cs b/GSS2.Core/Hardware/CameraService.cs
index ec53e1f..a66060a 100644
--- a/GSS2.Core/Hardware/CameraService.cs
+++ b/GSS2.Core/Hardware/CameraService.cs
@@ -9,13 +9,15 @@ namespace GSS2.Core.Hardware;
public class CameraService : IDisposable
{
- private static class LibC
+ public static class LibC
{
public const int PROT_READ = 0x01;
public const int MAP_SHARED = 0x0001;
[DllImport("libc", SetLastError = true)] public static extern IntPtr mmap(IntPtr address, ulong length, int prot, int flags, int fd, ulong offset);
[DllImport("libc", SetLastError = true)] public static extern int munmap(IntPtr address, ulong length);
+ [DllImport("libc", SetLastError = true)] public static extern int close(int fd);
+ [DllImport("libc", SetLastError = true)] public static extern int memfd_create(string name, uint flags);
}
private sealed class MappedBuffer
{
@@ -677,53 +679,67 @@ public class CameraService : IDisposable
var buffer = buffers.Skip(bufferId % buffers.Count()).First();
var request = _camera.CreateRequest(checked((ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()));
- var result = request.AddBuffer(_viewFinderStream, buffer);
+
+ int fd = LibC.memfd_create($"buffer_fence_{bufferId % buffers.Count()}", 0x0002U);
+ if (fd < 0)
+ {
+ throw new Exception($"memfd_create error: {Marshal.GetLastPInvokeError()} {Marshal.GetLastPInvokeErrorMessage()}");
+ }
+ Console.WriteLine($"Created fd {fd}");
+ var fence = new Fence(new UniqueFD(fd));
+ var result = request.AddBuffer(_viewFinderStream, buffer, fence);
if (result < 0)
+ {
+ var fenceFd = buffer.ReleaseFence()?.Fd?.Release();
+ Console.WriteLine($"Request queue failed, closing fd {fenceFd}");
+ if (fenceFd is not null)
+ LibC.close(fenceFd.Value);
throw new Exception("Error while request create");
+ }
// _logger.LogDebug("Request(s) created");
effectiveCancellationToken.ThrowIfCancellationRequested();
- var cts = new TaskCompletionSource();
- void RequestCompleted(object? sender, Camera.RequestCompletedEventArgs e)
- {
- if (request.Handle != e.Request.Handle)
- return;
+ // var cts = new TaskCompletionSource();
+ // void RequestCompleted(object? sender, Camera.RequestCompletedEventArgs e)
+ // {
+ // if (request.Handle != e.Request.Handle)
+ // return;
- var buffer = e.Request.FindBuffer(_viewFinderStream);
- if (buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameError ||
- buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameStartup)
- {
- // _logger.LogDebug("Request buffers status: {}", buffer.Metadata.Status);
- e.Request.Reuse(Request.ReuseFlagEnum.ReuseBuffers);
- var result = _camera.QueueRequest(e.Request);
- if (result >= 0)
- return;
- }
+ // var buffer = e.Request.FindBuffer(_viewFinderStream);
+ // if (buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameError ||
+ // buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameStartup)
+ // {
+ // // _logger.LogDebug("Request buffers status: {}", buffer.Metadata.Status);
+ // e.Request.Reuse(Request.ReuseFlagEnum.ReuseBuffers);
+ // var result = _camera.QueueRequest(e.Request);
+ // if (result >= 0)
+ // return;
+ // }
- // _logger.LogDebug("Request complited: \n\tStatus: {}\n\tCookie: {}\n\tSequence: {}\n\tHasPendingBuffers: {}", e.Request.Status, e.Request.Cookie, e.Request.Sequence, e.Request.HasPendingBuffers);
- // _logger.LogDebug("Request buffer: \n\tStatus: {} \n\tCookie: {} \n\tSequence: {} \n\tTimestamp: {}", buffer.Metadata.Status, buffer.Cookie, buffer.Metadata.Sequence, buffer.Metadata.Timestamp);
- // _logger.LogDebug("Request buffer planes: ");
- // foreach (var (i, plane) in buffer.Metadata.Planes.Enumerate())
- // _logger.LogDebug("Plane[{}]: bytes used: 0x{:X}", i, plane.BytesUsed);
- // foreach (var (i, plane) in buffer.Planes.Enumerate())
- // _logger.LogDebug("Plane[{}]: \n\tFd: 0x{:X} \n\tOffset: 0x{:X} \n\tLength: 0x{:X} \n\tKInvalidOffset: 0x{:X}", i, plane.Fd.Get(), plane.Offset, plane.Length, plane.KInvalidOffset);
+ // // _logger.LogDebug("Request complited: \n\tStatus: {}\n\tCookie: {}\n\tSequence: {}\n\tHasPendingBuffers: {}", e.Request.Status, e.Request.Cookie, e.Request.Sequence, e.Request.HasPendingBuffers);
+ // // _logger.LogDebug("Request buffer: \n\tStatus: {} \n\tCookie: {} \n\tSequence: {} \n\tTimestamp: {}", buffer.Metadata.Status, buffer.Cookie, buffer.Metadata.Sequence, buffer.Metadata.Timestamp);
+ // // _logger.LogDebug("Request buffer planes: ");
+ // // foreach (var (i, plane) in buffer.Metadata.Planes.Enumerate())
+ // // _logger.LogDebug("Plane[{}]: bytes used: 0x{:X}", i, plane.BytesUsed);
+ // // foreach (var (i, plane) in buffer.Planes.Enumerate())
+ // // _logger.LogDebug("Plane[{}]: \n\tFd: 0x{:X} \n\tOffset: 0x{:X} \n\tLength: 0x{:X} \n\tKInvalidOffset: 0x{:X}", i, plane.Fd.Get(), plane.Offset, plane.Length, plane.KInvalidOffset);
- effectiveCancellationToken.ThrowIfCancellationRequested();
+ // effectiveCancellationToken.ThrowIfCancellationRequested();
- cts.SetResult();
- }
+ // cts.SetResult();
+ // }
- _camera.RequestCompleted += RequestCompleted;
+ // _camera.RequestCompleted += RequestCompleted;
result = _camera.QueueRequest(request);
if (result < 0)
{
- _camera.RequestCompleted -= RequestCompleted;
+ // _camera.RequestCompleted -= RequestCompleted;
throw new Exception("Error while request queue");
}
// _logger.LogDebug("Request queued");
- await cts.Task.WaitAsync(effectiveCancellationToken);
- _camera.RequestCompleted -= RequestCompleted;
+ // await cts.Task.WaitAsync(effectiveCancellationToken);
+ // _camera.RequestCompleted -= RequestCompleted;
// _logger.LogDebug("Request complited");
return new(buffer, _viewFinderStreamConfiguration);
diff --git a/GSS2.Test/Views/CameraView.axaml.cs b/GSS2.Test/Views/CameraView.axaml.cs
index fdbd2c8..647f89d 100644
--- a/GSS2.Test/Views/CameraView.axaml.cs
+++ b/GSS2.Test/Views/CameraView.axaml.cs
@@ -30,6 +30,7 @@ class VulkanExportedImage
{
public required int ImageExportedSemaphoreFd { get; init; }
public required int ImageRenderedSemaphoreFd { get; init; }
+ public required int? FenceFd { get; init; }
public required int OrignalFd { get; init; }
public required int ImageFd { get; init; }
public required int ImageWidth { get; init; }
@@ -91,18 +92,18 @@ class VulkanRenderer
};
_context.KhrExternalSemaphoreFd.GetSemaphoreF(_context.Device, in imageRenderedSemaphoreGetFdInfoKHR, out var imageRenderedSemaphoreFd).ThrowOnError();
- // Silk.NET.Vulkan.Fence imageCapturedFence = new Silk.NET.Vulkan.Fence(null);
- // if (fenceFd is not null)
- // {
- // var importSemaphoreFdInfoKHR = new ImportFenceFdInfoKHR()
- // {
- // SType = StructureType.ImportSemaphoreFDInfoKhr,
- // Fd = fenceFd.Value,
- // Flags = FenceImportFlags.TemporaryBit,
- // HandleType = ExternalFenceHandleTypeFlags.SyncFDBit
- // };
- // _context.KhrExternalFenceFd.ImportFenceF(_context.Device, &importSemaphoreFdInfoKHR);
- // }
+ Silk.NET.Vulkan.Fence imageCapturedFence = new Silk.NET.Vulkan.Fence(null);
+ if (fenceFd is not null)
+ {
+ var importSemaphoreFdInfoKHR = new ImportFenceFdInfoKHR()
+ {
+ SType = StructureType.ImportSemaphoreFDInfoKhr,
+ Fd = fenceFd.Value,
+ Flags = FenceImportFlags.TemporaryBit,
+ HandleType = ExternalFenceHandleTypeFlags.OpaqueFDBit
+ };
+ _context.KhrExternalFenceFd.ImportFenceF(_context.Device, &importSemaphoreFdInfoKHR);
+ }
// Console.WriteLine("Import 9");
var (importImage, importMemoryReqirements, importMemory) = ImportImage(imageFdDuplicate, width, height, stride);
@@ -160,67 +161,71 @@ class VulkanRenderer
_context.KhrExternalMemoryFd.GetMemoryF(_context.Device, &memoryGetFdInfoKHR, out var vulkanImageFd).ThrowOnError();
// Console.WriteLine("Import 17");
- // var waitSemaphoreIndex = 0;
- // Silk.NET.Vulkan.Semaphore[] waitSemaphoresArray = new Silk.NET.Vulkan.Semaphore[
- // !initializationFrame ? 1 : 0
- // ];
- // PipelineStageFlags[] pipelineStageFlagsArray = new PipelineStageFlags[waitSemaphoresArray.Length];
- // if (!initializationFrame)
- // {
- // waitSemaphoresArray[waitSemaphoreIndex] = imageRenderedSemaphore;
- // pipelineStageFlagsArray[waitSemaphoreIndex++] = PipelineStageFlags.AllGraphicsBit;
- // }
- // var waitSemaphoresSpan = new ReadOnlySpan(waitSemaphoresArray);
- // var pipelineStageFlagsSpan = new ReadOnlySpan(pipelineStageFlagsArray);
-
- // fixed (PipelineStageFlags* pPipelineStageFlags = pipelineStageFlagsSpan)
- // {
- // fixed (Silk.NET.Vulkan.Semaphore* pWaitSemaphoresSpan = waitSemaphoresSpan)
- // {
- // var submitInfo = new SubmitInfo
- // {
- // SType = StructureType.SubmitInfo,
- // CommandBufferCount = 1,
- // PCommandBuffers = &commandBuffer,
- // PSignalSemaphores = &imageExportedSemaphore,
- // SignalSemaphoreCount = 1,
- // PWaitSemaphores = pWaitSemaphoresSpan,
- // PWaitDstStageMask = pPipelineStageFlags,
- // WaitSemaphoreCount = checked((uint)waitSemaphoresArray.Length)
- // };
- // // Console.WriteLine("Import 18");
- // _context.Api.QueueSubmit(_context.Queue, 1, &submitInfo, imageCapturedFence).ThrowOnError();
- // }
- // }
-
- ReadOnlySpan pipelineStageFlags = [PipelineStageFlags.AllGraphicsBit];
- fixed (PipelineStageFlags* pPipelineStageFlags = pipelineStageFlags)
+ var waitSemaphoreIndex = 0;
+ Silk.NET.Vulkan.Semaphore[] waitSemaphoresArray = new Silk.NET.Vulkan.Semaphore[
+ !initializationFrame ? 1 : 0
+ ];
+ PipelineStageFlags[] pipelineStageFlagsArray = new PipelineStageFlags[waitSemaphoresArray.Length];
+ if (!initializationFrame)
{
- ReadOnlySpan waitSemaphores =
- [
- imageRenderedSemaphore
- ];
- var submitInfo = new SubmitInfo
- {
- SType = StructureType.SubmitInfo,
- CommandBufferCount = 1,
- PCommandBuffers = &commandBuffer,
- PSignalSemaphores = &imageExportedSemaphore,
- SignalSemaphoreCount = 1,
- PWaitSemaphores = initializationFrame ? null : &imageRenderedSemaphore,
- WaitSemaphoreCount = initializationFrame ? 0u : 1u,
- PWaitDstStageMask = initializationFrame ? null : pPipelineStageFlags
- };
-
- // Console.WriteLine("Import 18");
- _context.Api.QueueSubmit(_context.Queue, 1, &submitInfo, new Silk.NET.Vulkan.Fence(UIntPtr.Zero)).ThrowOnError();
+ waitSemaphoresArray[waitSemaphoreIndex] = imageRenderedSemaphore;
+ pipelineStageFlagsArray[waitSemaphoreIndex++] = PipelineStageFlags.AllGraphicsBit;
}
+ var waitSemaphoresSpan = new ReadOnlySpan(waitSemaphoresArray);
+ var pipelineStageFlagsSpan = new ReadOnlySpan(pipelineStageFlagsArray);
+
+ _context.Api.Semaphore
+
+ fixed (PipelineStageFlags* pPipelineStageFlagsSpan = pipelineStageFlagsSpan)
+ {
+ fixed (Silk.NET.Vulkan.Semaphore* pWaitSemaphoresSpan = waitSemaphoresSpan)
+ {
+ var submitInfo = new SubmitInfo
+ {
+ SType = StructureType.SubmitInfo,
+ CommandBufferCount = 1,
+ PCommandBuffers = &commandBuffer,
+ PSignalSemaphores = &imageExportedSemaphore,
+ SignalSemaphoreCount = 1,
+ PWaitSemaphores = waitSemaphoresArray.Length == 0 ? null : pWaitSemaphoresSpan,
+ PWaitDstStageMask = waitSemaphoresArray.Length == 0 ? null : pPipelineStageFlagsSpan,
+ WaitSemaphoreCount = checked((uint)waitSemaphoresArray.Length)
+ };
+ // Console.WriteLine("Import 18");
+ Console.WriteLine(imageCapturedFence.Handle);
+ _context.Api.QueueSubmit(_context.Queue, 1, &submitInfo, imageCapturedFence).ThrowOnError();
+ }
+ }
+
+ // ReadOnlySpan pipelineStageFlags = [PipelineStageFlags.AllGraphicsBit];
+ // fixed (PipelineStageFlags* pPipelineStageFlags = pipelineStageFlags)
+ // {
+ // ReadOnlySpan waitSemaphores =
+ // [
+ // imageRenderedSemaphore
+ // ];
+ // var submitInfo = new SubmitInfo
+ // {
+ // SType = StructureType.SubmitInfo,
+ // CommandBufferCount = 1,
+ // PCommandBuffers = &commandBuffer,
+ // PSignalSemaphores = &imageExportedSemaphore,
+ // SignalSemaphoreCount = 1,
+ // PWaitSemaphores = initializationFrame ? null : &imageRenderedSemaphore,
+ // WaitSemaphoreCount = initializationFrame ? 0u : 1u,
+ // PWaitDstStageMask = initializationFrame ? null : pPipelineStageFlags
+ // };
+
+ // // Console.WriteLine("Import 18");
+ // _context.Api.QueueSubmit(_context.Queue, 1, &submitInfo, new Silk.NET.Vulkan.Fence(UIntPtr.Zero)).ThrowOnError();
+ // }
// Console.WriteLine("Import 19");
return new VulkanExportedImage
{
ImageExportedSemaphoreFd = imageExportedSemaphoreFd,
ImageRenderedSemaphoreFd = imageRenderedSemaphoreFd,
+ FenceFd = fenceFd,
OrignalFd = imageFdDuplicate,
ImageWidth = width,
ImageHeight = height,
@@ -251,6 +256,8 @@ class VulkanRenderer
_context.Api.FreeMemory(_context.Device, image.Resources.ImportMemory, null);
_context.Api.DestroyImage(_context.Device, image.Resources.ExportImage, null);
_context.Api.FreeMemory(_context.Device, image.Resources.ExportMemory, null);
+ if (image.FenceFd is not null)
+ close(image.FenceFd.Value);
close(image.OrignalFd);
close(image.ImageFd);
close(image.ImageExportedSemaphoreFd);
@@ -455,9 +462,9 @@ public partial class CameraView : Control
if (!_initialized)
return;
int i = 0;
- _updateTimer = new System.Timers.Timer(100)
+ _updateTimer = new System.Timers.Timer(105)
{
- AutoReset = true
+ AutoReset = false
};
_updateTimer.Elapsed += async (_, _) =>
{
@@ -471,8 +478,16 @@ public partial class CameraView : Control
if (result is not null)
{
var (frameBuffer, streamConfiguration) = result.Value;
- if (frameBuffer.Metadata.Status == FrameMetadata.StatusEnum.FrameSuccess)
- Update(frameBuffer, streamConfiguration);
+ // if (frameBuffer.Metadata.Status == FrameMetadata.StatusEnum.FrameSuccess)
+ Update(frameBuffer, streamConfiguration);
+ _updateTimer.Start();
+ // else
+ // {
+ // var fenceFd = frameBuffer.ReleaseFence()?.Fd?.Release();
+ // Console.WriteLine($"Buffer returned not success result, closing fd {fenceFd}");
+ // if (fenceFd is not null)
+ // GSS2.Core.Hardware.CameraService.LibC.close(fenceFd.Value);
+ // }
}
});
};
@@ -591,13 +606,14 @@ public partial class CameraView : Control
_renerer is not null)
{
// Console.WriteLine("Update 2");
- // var fenceFd = frameBuffer.ReleaseFence()?.Fd?.Release();
+ var fenceFd = frameBuffer.ReleaseFence()?.Fd?.Release();
+ Console.WriteLine($"Released fd {fenceFd}");
var image = _renerer.Import(
frameBuffer.Planes.First().Fd.Get(),
checked((int)streamConfiguration.Size.Width),
checked((int)streamConfiguration.Size.Height),
checked((int)streamConfiguration.Stride),
- null, // fenceFd,
+ fenceFd,
_initializationFrame);
// _renerer.ClearResource(image);
// Console.WriteLine("Update 3");
diff --git a/GSS2.Vulkan/VulkanExtensions.cs b/GSS2.Vulkan/VulkanExtensions.cs
index 72f41e1..262441d 100644
--- a/GSS2.Vulkan/VulkanExtensions.cs
+++ b/GSS2.Vulkan/VulkanExtensions.cs
@@ -11,7 +11,7 @@ public static class VulkanExtensions
{
public static void ThrowOnError(this Result result, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = -1)
{
- // Console.WriteLine($"{callerFilePath} {callerMemberName} {callerLineNumber} {result}");
+ Console.WriteLine($"{callerFilePath} {callerMemberName} {callerLineNumber} {result}");
if (result != Result.Success)
throw new Exception($"Unexpected API error \"{result}\"");
}