public void CopyTo(ITexture destination, int firstLayer, int firstLevel) { _gd.FlushAllCommands(); var src = this; var dst = (TextureView)destination; if (!Valid || !dst.Valid) { return; } using var cbs = _gd.CommandBufferPool.Rent(); var srcImage = src.GetImage().Get(cbs).Value; var dstImage = dst.GetImage().Get(cbs).Value; TextureCopy.Copy( _gd.Api, cbs.CommandBuffer, srcImage, dstImage, src.Info, dst.Info, src.FirstLayer, dst.FirstLayer, src.FirstLevel, dst.FirstLevel, 0, firstLayer, 0, firstLevel); }
public unsafe void SetData(int offset, ReadOnlySpan <byte> data, CommandBufferScoped?cbs = null, Action endRenderPass = null) { int dataSize = Math.Min(data.Length, Size - offset); if (dataSize == 0) { return; } bool needsFlush = _gd.CommandBufferPool.HasWaitableOnRentedCommandBuffer(_waitable, offset, dataSize); bool needsWait = needsFlush || MayWait(offset, dataSize); if (cbs == null || !needsWait || !VulkanConfiguration.UseFastBufferUpdates || !TryPushData(cbs.Value, endRenderPass, offset, data)) { // Some pending command might access the buffer, // so we need to ensure they are all submited to the GPU before waiting. // The flush below forces the submission of all pending commands. if (needsFlush) { _gd.FlushAllCommands(); } WaitForFences(offset, dataSize); if (_map != IntPtr.Zero) { data.Slice(0, dataSize).CopyTo(new Span <byte>((void *)(_map + offset), dataSize)); } } }
public void Create(ulong id) { MultiFenceHolder waitable = new MultiFenceHolder(); _gd.FlushAllCommands(); _gd.CommandBufferPool.AddWaitable(waitable); SyncHandle handle = new SyncHandle { ID = id, Waitable = waitable }; lock (_handles) { _handles.Add(handle); } }
public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback) { uint nextImage = 0; while (true) { var acquireResult = _gd.SwapchainApi.AcquireNextImage( _device, _swapchain, ulong.MaxValue, _imageAvailableSemaphore, new Fence(), ref nextImage); if (acquireResult == Result.ErrorOutOfDateKhr || acquireResult == Result.SuboptimalKhr) { RecreateSwapchain(); } else { acquireResult.ThrowOnError(); break; } } var swapchainImage = _swapchainImages[nextImage]; _gd.FlushAllCommands(); var cbs = _gd.CommandBufferPool.Rent(); Transition( cbs.CommandBuffer, swapchainImage, 0, AccessFlags.AccessTransferWriteBit, ImageLayout.Undefined, ImageLayout.General); var view = (TextureView)texture; int srcX0, srcX1, srcY0, srcY1; float scale = view.ScaleFactor; if (crop.Left == 0 && crop.Right == 0) { srcX0 = 0; srcX1 = (int)(view.Width / scale); } else { srcX0 = crop.Left; srcX1 = crop.Right; } if (crop.Top == 0 && crop.Bottom == 0) { srcY0 = 0; srcY1 = (int)(view.Height / scale); } else { srcY0 = crop.Top; srcY1 = crop.Bottom; } if (scale != 1f) { srcX0 = (int)(srcX0 * scale); srcY0 = (int)(srcY0 * scale); srcX1 = (int)Math.Ceiling(srcX1 * scale); srcY1 = (int)Math.Ceiling(srcY1 * scale); } if (ScreenCaptureRequested) { CaptureFrame(view, srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0, view.Info.Format.IsBgr(), crop.FlipX, crop.FlipY); ScreenCaptureRequested = false; } float ratioX = MathF.Min(1f, (_height * (float)SurfaceWidth) / ((float)SurfaceHeight * _width)); float ratioY = MathF.Min(1f, (_width * (float)SurfaceHeight) / ((float)SurfaceWidth * _height)); int dstWidth = (int)(_width * ratioX); int dstHeight = (int)(_height * ratioY); int dstPaddingX = (_width - dstWidth) / 2; int dstPaddingY = (_height - dstHeight) / 2; int dstX0 = crop.FlipX ? _width - dstPaddingX : dstPaddingX; int dstX1 = crop.FlipX ? dstPaddingX : _width - dstPaddingX; int dstY0 = crop.FlipY ? dstPaddingY : _height - dstPaddingY; int dstY1 = crop.FlipY ? _height - dstPaddingY : dstPaddingY; _gd.HelperShader.Blit( _gd, cbs, view, _swapchainImageViews[nextImage], _width, _height, _format, new Extents2D(srcX0, srcY0, srcX1, srcY1), new Extents2D(dstX0, dstY1, dstX1, dstY0), true, true); Transition( cbs.CommandBuffer, swapchainImage, 0, 0, ImageLayout.General, ImageLayout.PresentSrcKhr); _gd.CommandBufferPool.Return( cbs, new[] { _imageAvailableSemaphore }, new[] { PipelineStageFlags.PipelineStageColorAttachmentOutputBit }, new[] { _renderFinishedSemaphore }); // TODO: Present queue. var semaphore = _renderFinishedSemaphore; var swapchain = _swapchain; Result result; var presentInfo = new PresentInfoKHR() { SType = StructureType.PresentInfoKhr, WaitSemaphoreCount = 1, PWaitSemaphores = &semaphore, SwapchainCount = 1, PSwapchains = &swapchain, PImageIndices = &nextImage, PResults = &result }; _gd.SwapchainApi.QueuePresent(_gd.Queue, presentInfo); }