forked from amkovkov/GranuSightSoftware2
feat: CameraView + CameraService fences
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
<PackageReference Include="OpenCvSharp4.runtime.linux-arm" Version="4.11.0.20250506" />
|
<PackageReference Include="OpenCvSharp4.runtime.linux-arm" Version="4.11.0.20250506" />
|
||||||
<PackageReference Include="System.Device.Gpio" Version="4.0.1" />
|
<PackageReference Include="System.Device.Gpio" Version="4.0.1" />
|
||||||
<PackageReference Include="Iot.Device.Bindings" Version="4.0.1" />
|
<PackageReference Include="Iot.Device.Bindings" Version="4.0.1" />
|
||||||
<PackageReference Include="LibCameraSharp" Version="0.5.2-20260129-5" />
|
<PackageReference Include="LibCameraSharp" Version="0.5.2-20260129-7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ namespace GSS2.Core.Hardware;
|
|||||||
|
|
||||||
public class CameraService : IDisposable
|
public class CameraService : IDisposable
|
||||||
{
|
{
|
||||||
private static class LibC
|
public static class LibC
|
||||||
{
|
{
|
||||||
public const int PROT_READ = 0x01;
|
public const int PROT_READ = 0x01;
|
||||||
public const int MAP_SHARED = 0x0001;
|
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 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 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
|
private sealed class MappedBuffer
|
||||||
{
|
{
|
||||||
@@ -677,53 +679,67 @@ public class CameraService : IDisposable
|
|||||||
var buffer = buffers.Skip(bufferId % buffers.Count()).First();
|
var buffer = buffers.Skip(bufferId % buffers.Count()).First();
|
||||||
|
|
||||||
var request = _camera.CreateRequest(checked((ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()));
|
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)
|
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");
|
throw new Exception("Error while request create");
|
||||||
|
}
|
||||||
// _logger.LogDebug("Request(s) created");
|
// _logger.LogDebug("Request(s) created");
|
||||||
|
|
||||||
effectiveCancellationToken.ThrowIfCancellationRequested();
|
effectiveCancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var cts = new TaskCompletionSource();
|
// var cts = new TaskCompletionSource();
|
||||||
void RequestCompleted(object? sender, Camera.RequestCompletedEventArgs e)
|
// void RequestCompleted(object? sender, Camera.RequestCompletedEventArgs e)
|
||||||
{
|
// {
|
||||||
if (request.Handle != e.Request.Handle)
|
// if (request.Handle != e.Request.Handle)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
var buffer = e.Request.FindBuffer(_viewFinderStream);
|
// var buffer = e.Request.FindBuffer(_viewFinderStream);
|
||||||
if (buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameError ||
|
// if (buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameError ||
|
||||||
buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameStartup)
|
// buffer.Metadata.Status == FrameMetadata.StatusEnum.FrameStartup)
|
||||||
{
|
// {
|
||||||
// _logger.LogDebug("Request buffers status: {}", buffer.Metadata.Status);
|
// // _logger.LogDebug("Request buffers status: {}", buffer.Metadata.Status);
|
||||||
e.Request.Reuse(Request.ReuseFlagEnum.ReuseBuffers);
|
// e.Request.Reuse(Request.ReuseFlagEnum.ReuseBuffers);
|
||||||
var result = _camera.QueueRequest(e.Request);
|
// var result = _camera.QueueRequest(e.Request);
|
||||||
if (result >= 0)
|
// if (result >= 0)
|
||||||
return;
|
// 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 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: \n\tStatus: {} \n\tCookie: {} \n\tSequence: {} \n\tTimestamp: {}", buffer.Metadata.Status, buffer.Cookie, buffer.Metadata.Sequence, buffer.Metadata.Timestamp);
|
||||||
// _logger.LogDebug("Request buffer planes: ");
|
// // _logger.LogDebug("Request buffer planes: ");
|
||||||
// foreach (var (i, plane) in buffer.Metadata.Planes.Enumerate())
|
// // foreach (var (i, plane) in buffer.Metadata.Planes.Enumerate())
|
||||||
// _logger.LogDebug("Plane[{}]: bytes used: 0x{:X}", i, plane.BytesUsed);
|
// // _logger.LogDebug("Plane[{}]: bytes used: 0x{:X}", i, plane.BytesUsed);
|
||||||
// foreach (var (i, plane) in buffer.Planes.Enumerate())
|
// // 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("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);
|
result = _camera.QueueRequest(request);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
_camera.RequestCompleted -= RequestCompleted;
|
// _camera.RequestCompleted -= RequestCompleted;
|
||||||
throw new Exception("Error while request queue");
|
throw new Exception("Error while request queue");
|
||||||
}
|
}
|
||||||
// _logger.LogDebug("Request queued");
|
// _logger.LogDebug("Request queued");
|
||||||
await cts.Task.WaitAsync(effectiveCancellationToken);
|
// await cts.Task.WaitAsync(effectiveCancellationToken);
|
||||||
_camera.RequestCompleted -= RequestCompleted;
|
// _camera.RequestCompleted -= RequestCompleted;
|
||||||
// _logger.LogDebug("Request complited");
|
// _logger.LogDebug("Request complited");
|
||||||
|
|
||||||
return new(buffer, _viewFinderStreamConfiguration);
|
return new(buffer, _viewFinderStreamConfiguration);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class VulkanExportedImage
|
|||||||
{
|
{
|
||||||
public required int ImageExportedSemaphoreFd { get; init; }
|
public required int ImageExportedSemaphoreFd { get; init; }
|
||||||
public required int ImageRenderedSemaphoreFd { get; init; }
|
public required int ImageRenderedSemaphoreFd { get; init; }
|
||||||
|
public required int? FenceFd { get; init; }
|
||||||
public required int OrignalFd { get; init; }
|
public required int OrignalFd { get; init; }
|
||||||
public required int ImageFd { get; init; }
|
public required int ImageFd { get; init; }
|
||||||
public required int ImageWidth { 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();
|
_context.KhrExternalSemaphoreFd.GetSemaphoreF(_context.Device, in imageRenderedSemaphoreGetFdInfoKHR, out var imageRenderedSemaphoreFd).ThrowOnError();
|
||||||
|
|
||||||
// Silk.NET.Vulkan.Fence imageCapturedFence = new Silk.NET.Vulkan.Fence(null);
|
Silk.NET.Vulkan.Fence imageCapturedFence = new Silk.NET.Vulkan.Fence(null);
|
||||||
// if (fenceFd is not null)
|
if (fenceFd is not null)
|
||||||
// {
|
{
|
||||||
// var importSemaphoreFdInfoKHR = new ImportFenceFdInfoKHR()
|
var importSemaphoreFdInfoKHR = new ImportFenceFdInfoKHR()
|
||||||
// {
|
{
|
||||||
// SType = StructureType.ImportSemaphoreFDInfoKhr,
|
SType = StructureType.ImportSemaphoreFDInfoKhr,
|
||||||
// Fd = fenceFd.Value,
|
Fd = fenceFd.Value,
|
||||||
// Flags = FenceImportFlags.TemporaryBit,
|
Flags = FenceImportFlags.TemporaryBit,
|
||||||
// HandleType = ExternalFenceHandleTypeFlags.SyncFDBit
|
HandleType = ExternalFenceHandleTypeFlags.OpaqueFDBit
|
||||||
// };
|
};
|
||||||
// _context.KhrExternalFenceFd.ImportFenceF(_context.Device, &importSemaphoreFdInfoKHR);
|
_context.KhrExternalFenceFd.ImportFenceF(_context.Device, &importSemaphoreFdInfoKHR);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Console.WriteLine("Import 9");
|
// Console.WriteLine("Import 9");
|
||||||
var (importImage, importMemoryReqirements, importMemory) = ImportImage(imageFdDuplicate, width, height, stride);
|
var (importImage, importMemoryReqirements, importMemory) = ImportImage(imageFdDuplicate, width, height, stride);
|
||||||
@@ -160,46 +161,25 @@ class VulkanRenderer
|
|||||||
_context.KhrExternalMemoryFd.GetMemoryF(_context.Device, &memoryGetFdInfoKHR, out var vulkanImageFd).ThrowOnError();
|
_context.KhrExternalMemoryFd.GetMemoryF(_context.Device, &memoryGetFdInfoKHR, out var vulkanImageFd).ThrowOnError();
|
||||||
|
|
||||||
// Console.WriteLine("Import 17");
|
// Console.WriteLine("Import 17");
|
||||||
// var waitSemaphoreIndex = 0;
|
var waitSemaphoreIndex = 0;
|
||||||
// Silk.NET.Vulkan.Semaphore[] waitSemaphoresArray = new Silk.NET.Vulkan.Semaphore[
|
Silk.NET.Vulkan.Semaphore[] waitSemaphoresArray = new Silk.NET.Vulkan.Semaphore[
|
||||||
// !initializationFrame ? 1 : 0
|
!initializationFrame ? 1 : 0
|
||||||
// ];
|
|
||||||
// PipelineStageFlags[] pipelineStageFlagsArray = new PipelineStageFlags[waitSemaphoresArray.Length];
|
|
||||||
// if (!initializationFrame)
|
|
||||||
// {
|
|
||||||
// waitSemaphoresArray[waitSemaphoreIndex] = imageRenderedSemaphore;
|
|
||||||
// pipelineStageFlagsArray[waitSemaphoreIndex++] = PipelineStageFlags.AllGraphicsBit;
|
|
||||||
// }
|
|
||||||
// var waitSemaphoresSpan = new ReadOnlySpan<Silk.NET.Vulkan.Semaphore>(waitSemaphoresArray);
|
|
||||||
// var pipelineStageFlagsSpan = new ReadOnlySpan<PipelineStageFlags>(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 = [PipelineStageFlags.AllGraphicsBit];
|
|
||||||
fixed (PipelineStageFlags* pPipelineStageFlags = pipelineStageFlags)
|
|
||||||
{
|
|
||||||
ReadOnlySpan<Silk.NET.Vulkan.Semaphore> waitSemaphores =
|
|
||||||
[
|
|
||||||
imageRenderedSemaphore
|
|
||||||
];
|
];
|
||||||
|
PipelineStageFlags[] pipelineStageFlagsArray = new PipelineStageFlags[waitSemaphoresArray.Length];
|
||||||
|
if (!initializationFrame)
|
||||||
|
{
|
||||||
|
waitSemaphoresArray[waitSemaphoreIndex] = imageRenderedSemaphore;
|
||||||
|
pipelineStageFlagsArray[waitSemaphoreIndex++] = PipelineStageFlags.AllGraphicsBit;
|
||||||
|
}
|
||||||
|
var waitSemaphoresSpan = new ReadOnlySpan<Silk.NET.Vulkan.Semaphore>(waitSemaphoresArray);
|
||||||
|
var pipelineStageFlagsSpan = new ReadOnlySpan<PipelineStageFlags>(pipelineStageFlagsArray);
|
||||||
|
|
||||||
|
_context.Api.Semaphore
|
||||||
|
|
||||||
|
fixed (PipelineStageFlags* pPipelineStageFlagsSpan = pipelineStageFlagsSpan)
|
||||||
|
{
|
||||||
|
fixed (Silk.NET.Vulkan.Semaphore* pWaitSemaphoresSpan = waitSemaphoresSpan)
|
||||||
|
{
|
||||||
var submitInfo = new SubmitInfo
|
var submitInfo = new SubmitInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.SubmitInfo,
|
SType = StructureType.SubmitInfo,
|
||||||
@@ -207,20 +187,45 @@ class VulkanRenderer
|
|||||||
PCommandBuffers = &commandBuffer,
|
PCommandBuffers = &commandBuffer,
|
||||||
PSignalSemaphores = &imageExportedSemaphore,
|
PSignalSemaphores = &imageExportedSemaphore,
|
||||||
SignalSemaphoreCount = 1,
|
SignalSemaphoreCount = 1,
|
||||||
PWaitSemaphores = initializationFrame ? null : &imageRenderedSemaphore,
|
PWaitSemaphores = waitSemaphoresArray.Length == 0 ? null : pWaitSemaphoresSpan,
|
||||||
WaitSemaphoreCount = initializationFrame ? 0u : 1u,
|
PWaitDstStageMask = waitSemaphoresArray.Length == 0 ? null : pPipelineStageFlagsSpan,
|
||||||
PWaitDstStageMask = initializationFrame ? null : pPipelineStageFlags
|
WaitSemaphoreCount = checked((uint)waitSemaphoresArray.Length)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Console.WriteLine("Import 18");
|
// Console.WriteLine("Import 18");
|
||||||
_context.Api.QueueSubmit(_context.Queue, 1, &submitInfo, new Silk.NET.Vulkan.Fence(UIntPtr.Zero)).ThrowOnError();
|
Console.WriteLine(imageCapturedFence.Handle);
|
||||||
|
_context.Api.QueueSubmit(_context.Queue, 1, &submitInfo, imageCapturedFence).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadOnlySpan<PipelineStageFlags> pipelineStageFlags = [PipelineStageFlags.AllGraphicsBit];
|
||||||
|
// fixed (PipelineStageFlags* pPipelineStageFlags = pipelineStageFlags)
|
||||||
|
// {
|
||||||
|
// ReadOnlySpan<Silk.NET.Vulkan.Semaphore> 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");
|
// Console.WriteLine("Import 19");
|
||||||
return new VulkanExportedImage
|
return new VulkanExportedImage
|
||||||
{
|
{
|
||||||
ImageExportedSemaphoreFd = imageExportedSemaphoreFd,
|
ImageExportedSemaphoreFd = imageExportedSemaphoreFd,
|
||||||
ImageRenderedSemaphoreFd = imageRenderedSemaphoreFd,
|
ImageRenderedSemaphoreFd = imageRenderedSemaphoreFd,
|
||||||
|
FenceFd = fenceFd,
|
||||||
OrignalFd = imageFdDuplicate,
|
OrignalFd = imageFdDuplicate,
|
||||||
ImageWidth = width,
|
ImageWidth = width,
|
||||||
ImageHeight = height,
|
ImageHeight = height,
|
||||||
@@ -251,6 +256,8 @@ class VulkanRenderer
|
|||||||
_context.Api.FreeMemory(_context.Device, image.Resources.ImportMemory, null);
|
_context.Api.FreeMemory(_context.Device, image.Resources.ImportMemory, null);
|
||||||
_context.Api.DestroyImage(_context.Device, image.Resources.ExportImage, null);
|
_context.Api.DestroyImage(_context.Device, image.Resources.ExportImage, null);
|
||||||
_context.Api.FreeMemory(_context.Device, image.Resources.ExportMemory, 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.OrignalFd);
|
||||||
close(image.ImageFd);
|
close(image.ImageFd);
|
||||||
close(image.ImageExportedSemaphoreFd);
|
close(image.ImageExportedSemaphoreFd);
|
||||||
@@ -455,9 +462,9 @@ public partial class CameraView : Control
|
|||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
return;
|
return;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
_updateTimer = new System.Timers.Timer(100)
|
_updateTimer = new System.Timers.Timer(105)
|
||||||
{
|
{
|
||||||
AutoReset = true
|
AutoReset = false
|
||||||
};
|
};
|
||||||
_updateTimer.Elapsed += async (_, _) =>
|
_updateTimer.Elapsed += async (_, _) =>
|
||||||
{
|
{
|
||||||
@@ -471,8 +478,16 @@ public partial class CameraView : Control
|
|||||||
if (result is not null)
|
if (result is not null)
|
||||||
{
|
{
|
||||||
var (frameBuffer, streamConfiguration) = result.Value;
|
var (frameBuffer, streamConfiguration) = result.Value;
|
||||||
if (frameBuffer.Metadata.Status == FrameMetadata.StatusEnum.FrameSuccess)
|
// if (frameBuffer.Metadata.Status == FrameMetadata.StatusEnum.FrameSuccess)
|
||||||
Update(frameBuffer, streamConfiguration);
|
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)
|
_renerer is not null)
|
||||||
{
|
{
|
||||||
// Console.WriteLine("Update 2");
|
// 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(
|
var image = _renerer.Import(
|
||||||
frameBuffer.Planes.First().Fd.Get(),
|
frameBuffer.Planes.First().Fd.Get(),
|
||||||
checked((int)streamConfiguration.Size.Width),
|
checked((int)streamConfiguration.Size.Width),
|
||||||
checked((int)streamConfiguration.Size.Height),
|
checked((int)streamConfiguration.Size.Height),
|
||||||
checked((int)streamConfiguration.Stride),
|
checked((int)streamConfiguration.Stride),
|
||||||
null, // fenceFd,
|
fenceFd,
|
||||||
_initializationFrame);
|
_initializationFrame);
|
||||||
// _renerer.ClearResource(image);
|
// _renerer.ClearResource(image);
|
||||||
// Console.WriteLine("Update 3");
|
// Console.WriteLine("Update 3");
|
||||||
|
|||||||
@@ -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)
|
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)
|
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