예제 #1
0
        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);
        }
예제 #2
0
        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));
                }
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
        }