Ejemplo n.º 1
0
        protected override void ResolveTextureCore(Texture source, Texture destination)
        {
            if (_activeRenderPass != VkRenderPass.Null)
            {
                EndCurrentRenderPass();
            }

            VkTexture          vkSource      = Util.AssertSubtype <Texture, VkTexture>(source);
            VkTexture          vkDestination = Util.AssertSubtype <Texture, VkTexture>(destination);
            VkImageAspectFlags aspectFlags   = ((source.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil)
                ? VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil
                : VkImageAspectFlags.Color;
            VkImageResolve region = new VkImageResolve
            {
                extent = new VkExtent3D {
                    width = source.Width, height = source.Height, depth = source.Depth
                },
                srcSubresource = new VkImageSubresourceLayers {
                    layerCount = 1, aspectMask = aspectFlags
                },
                dstSubresource = new VkImageSubresourceLayers {
                    layerCount = 1, aspectMask = aspectFlags
                }
            };

            vkCmdResolveImage(
                _cb,
                vkSource.OptimalDeviceImage,
                vkSource.GetImageLayout(0, 0),
                vkDestination.OptimalDeviceImage,
                vkDestination.GetImageLayout(0, 0),
                1,
                ref region);
        }
Ejemplo n.º 2
0
 public override void TransitionToFinalLayout(VkCommandBuffer cb)
 {
     for (int i = 0; i < ColorTargets.Count; i++)
     {
         FramebufferAttachment ca    = ColorTargets[i];
         VkTexture             vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         if ((vkTex.Usage & TextureUsage.Sampled) != 0)
         {
             vkTex.TransitionImageLayout(
                 cb,
                 ca.MipLevel, 1,
                 ca.ArrayLayer, 1,
                 VkImageLayout.ShaderReadOnlyOptimal);
         }
     }
     if (DepthTarget != null)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target);
         if ((vkTex.Usage & TextureUsage.Sampled) != 0)
         {
             vkTex.TransitionImageLayout(
                 cb,
                 DepthTarget.Value.MipLevel, 1,
                 DepthTarget.Value.ArrayLayer, 1,
                 VkImageLayout.ShaderReadOnlyOptimal);
         }
     }
 }
Ejemplo n.º 3
0
 public override void TransitionToFinalLayout(VkCommandBuffer cb)
 {
     foreach (FramebufferAttachment ca in ColorTargets)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         vkTex.SetImageLayout(ca.MipLevel, ca.ArrayLayer, VkImageLayout.ColorAttachmentOptimal);
         if ((vkTex.Usage & TextureUsage.Sampled) != 0)
         {
             vkTex.TransitionImageLayout(
                 cb,
                 ca.MipLevel, 1,
                 ca.ArrayLayer, 1,
                 VkImageLayout.ShaderReadOnlyOptimal);
         }
     }
     if (DepthTarget != null)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target);
         vkTex.SetImageLayout(
             DepthTarget.Value.MipLevel,
             DepthTarget.Value.ArrayLayer,
             VkImageLayout.DepthStencilAttachmentOptimal);
         if ((vkTex.Usage & TextureUsage.Sampled) != 0)
         {
             vkTex.TransitionImageLayout(
                 cb,
                 DepthTarget.Value.MipLevel, 1,
                 DepthTarget.Value.ArrayLayer, 1,
                 VkImageLayout.ShaderReadOnlyOptimal);
         }
     }
 }
Ejemplo n.º 4
0
        private void CreateFramebuffers()
        {
            if (_scFramebuffers != null)
            {
                for (int i = 0; i < _scFramebuffers.Length; i++)
                {
                    _scFramebuffers[i]?.Dispose();
                    _scFramebuffers[i] = null;
                }
                Array.Clear(_scFramebuffers, 0, _scFramebuffers.Length);
            }

            Util.EnsureArrayMinimumSize(ref _scFramebuffers, (uint)_scImages.Length);
            Util.EnsureArrayMinimumSize(ref _scColorTextures, (uint)_scImages.Length);
            for (uint i = 0; i < _scImages.Length; i++)
            {
                VkTexture colorTex = new VkTexture(
                    _gd,
                    Math.Max(1, _scExtent.width),
                    Math.Max(1, _scExtent.height),
                    1,
                    1,
                    _scImageFormat,
                    TextureUsage.RenderTarget,
                    TextureSampleCount.Count1,
                    _scImages[i]);
                FramebufferDescription desc = new FramebufferDescription(_depthAttachment?.Target, colorTex);
                VkFramebuffer          fb   = new VkFramebuffer(_gd, ref desc, true);
                _scFramebuffers[i]  = fb;
                _scColorTextures[i] = new FramebufferAttachment[] { new FramebufferAttachment(colorTex, 0) };
            }
        }
Ejemplo n.º 5
0
 public override void TransitionToFinalLayout(VkCommandBuffer cb)
 {
     foreach (FramebufferAttachment ca in ColorTargets)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         vkTex.TransitionImageLayout(cb, 0, 1, ca.ArrayLayer, 1, VkImageLayout.PresentSrcKHR);
     }
 }
Ejemplo n.º 6
0
 public override void TransitionToIntermediateLayout(VkCommandBuffer cb)
 {
     foreach (FramebufferAttachment ca in ColorTargets)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         vkTex.SetImageLayout(0, ca.ArrayLayer, VkImageLayout.ColorAttachmentOptimal);
     }
 }
Ejemplo n.º 7
0
        public VkTextureView(VkGraphicsDevice gd, ref TextureViewDescription description)
            : base(ref description)
        {
            _gd = gd;
            VkImageViewCreateInfo imageViewCI = VkImageViewCreateInfo.New();
            VkTexture             tex         = Util.AssertSubtype <Texture, VkTexture>(description.Target);

            imageViewCI.image  = tex.OptimalDeviceImage;
            imageViewCI.format = VkFormats.VdToVkPixelFormat(Format, (Target.Usage & TextureUsage.DepthStencil) != 0);

            VkImageAspectFlags aspectFlags;

            if ((description.Target.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil)
            {
                aspectFlags = VkImageAspectFlags.Depth;
            }
            else
            {
                aspectFlags = VkImageAspectFlags.Color;
            }

            imageViewCI.subresourceRange = new VkImageSubresourceRange(
                aspectFlags,
                description.BaseMipLevel,
                description.MipLevels,
                description.BaseArrayLayer,
                description.ArrayLayers);

            if ((tex.Usage & TextureUsage.Cubemap) == TextureUsage.Cubemap)
            {
                imageViewCI.viewType = description.ArrayLayers == 1 ? VkImageViewType.ImageCube : VkImageViewType.ImageCubeArray;
                imageViewCI.subresourceRange.layerCount *= 6;
            }
            else
            {
                switch (tex.Type)
                {
                case TextureType.Texture1D:
                    imageViewCI.viewType = description.ArrayLayers == 1
                            ? VkImageViewType.Image1D
                            : VkImageViewType.Image1DArray;
                    break;

                case TextureType.Texture2D:
                    imageViewCI.viewType = description.ArrayLayers == 1
                            ? VkImageViewType.Image2D
                            : VkImageViewType.Image2DArray;
                    break;

                case TextureType.Texture3D:
                    imageViewCI.viewType = VkImageViewType.Image3D;
                    break;
                }
            }

            vkCreateImageView(_gd.Device, ref imageViewCI, null, out _imageView);
            RefCount = new ResourceRefCount(DisposeCore);
        }
Ejemplo n.º 8
0
        protected override void GenerateMipmapsCore(Texture texture)
        {
            EnsureNoRenderPass();
            VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(texture);

            vkTex.TransitionImageLayout(_cb, 0, 1, 0, vkTex.ArrayLayers, VkImageLayout.TransferSrcOptimal);
            vkTex.TransitionImageLayout(_cb, 1, vkTex.MipLevels - 1, 0, vkTex.ArrayLayers, VkImageLayout.TransferDstOptimal);

            VkImage deviceImage = vkTex.OptimalDeviceImage;

            uint         blitCount = vkTex.MipLevels - 1;
            VkImageBlit *regions   = stackalloc VkImageBlit[(int)blitCount];

            for (uint level = 1; level < vkTex.MipLevels; level++)
            {
                uint blitIndex = level - 1;

                regions[blitIndex].srcSubresource = new VkImageSubresourceLayers
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    baseArrayLayer = 0,
                    layerCount     = vkTex.ArrayLayers,
                    mipLevel       = 0
                };
                regions[blitIndex].srcOffsets_0 = new VkOffset3D();
                regions[blitIndex].srcOffsets_1 = new VkOffset3D {
                    x = (int)vkTex.Width, y = (int)vkTex.Height, z = (int)vkTex.Depth
                };
                regions[blitIndex].dstOffsets_0 = new VkOffset3D();

                regions[blitIndex].dstSubresource = new VkImageSubresourceLayers
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    baseArrayLayer = 0,
                    layerCount     = vkTex.ArrayLayers,
                    mipLevel       = level
                };

                Util.GetMipDimensions(vkTex, level, out uint mipWidth, out uint mipHeight, out uint mipDepth);
                regions[blitIndex].dstOffsets_1 = new VkOffset3D {
                    x = (int)mipWidth, y = (int)mipHeight, z = (int)mipDepth
                };
            }

            vkCmdBlitImage(
                _cb,
                deviceImage, VkImageLayout.TransferSrcOptimal,
                deviceImage, VkImageLayout.TransferDstOptimal,
                blitCount, regions,
                _gd.GetFormatFilter(vkTex.VkFormat));

            if ((vkTex.Usage & TextureUsage.Sampled) != 0)
            {
                // This is somewhat ugly -- the transition logic does not handle different source layouts, so we do two batches.
                vkTex.TransitionImageLayout(_cb, 0, 1, 0, vkTex.ArrayLayers, VkImageLayout.ShaderReadOnlyOptimal);
                vkTex.TransitionImageLayout(_cb, 1, vkTex.MipLevels - 1, 0, vkTex.ArrayLayers, VkImageLayout.ShaderReadOnlyOptimal);
            }
        }
Ejemplo n.º 9
0
 public override void TransitionToIntermediateLayout(VkCommandBuffer cb)
 {
     for (int i = 0; i < ColorTargets.Count; i++)
     {
         FramebufferAttachment ca    = ColorTargets[i];
         VkTexture             vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         vkTex.SetImageLayout(0, ca.ArrayLayer, VkImageLayout.ColorAttachmentOptimal);
     }
 }
Ejemplo n.º 10
0
 public override void TransitionToFinalLayout(VkCommandBuffer cb)
 {
     for (int i = 0; i < ColorTargets.Count; i++)
     {
         FramebufferAttachment ca    = ColorTargets[i];
         VkTexture             vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         vkTex.TransitionImageLayout(cb, 0, 1, ca.ArrayLayer, 1, VkImageLayout.PresentSrcKHR);
     }
 }
Ejemplo n.º 11
0
 private void CreateDepthTexture()
 {
     _depthTexture?.Dispose();
     _depthTexture = (VkTexture)_gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                      _scExtent.width,
                                                                      _scExtent.height,
                                                                      1,
                                                                      1,
                                                                      1,
                                                                      PixelFormat.R16_UNorm,
                                                                      TextureUsage.DepthStencil));
 }
Ejemplo n.º 12
0
 private void CreateDepthTexture()
 {
     if (_depthFormat.HasValue)
     {
         _depthAttachment?.Target.Dispose();
         VkTexture depthTexture = (VkTexture)_gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D(
                                                                                   Math.Max(1, _scExtent.width),
                                                                                   Math.Max(1, _scExtent.height),
                                                                                   1,
                                                                                   1,
                                                                                   _depthFormat.Value,
                                                                                   TextureUsage.DepthStencil));
         _depthAttachment = new FramebufferAttachment(depthTexture, 0);
     }
 }
Ejemplo n.º 13
0
 public override void TransitionToIntermediateLayout(VkCommandBuffer cb)
 {
     foreach (FramebufferAttachment ca in ColorTargets)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(ca.Target);
         vkTex.SetImageLayout(ca.MipLevel, ca.ArrayLayer, VkImageLayout.ColorAttachmentOptimal);
     }
     if (DepthTarget != null)
     {
         VkTexture vkTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target);
         vkTex.SetImageLayout(
             DepthTarget.Value.MipLevel,
             DepthTarget.Value.ArrayLayer,
             VkImageLayout.DepthStencilAttachmentOptimal);
     }
 }
Ejemplo n.º 14
0
        public VkTextureView(VkGraphicsDevice gd, ref TextureViewDescription description)
            : base(ref description)
        {
            _gd = gd;
            VkImageViewCreateInfo imageViewCI = VkImageViewCreateInfo.New();
            VkTexture             tex         = Util.AssertSubtype <Texture, VkTexture>(description.Target);

            imageViewCI.image  = tex.OptimalDeviceImage;
            imageViewCI.format = tex.VkFormat;

            VkImageAspectFlags aspectFlags;

            if ((description.Target.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil)
            {
                aspectFlags = VkImageAspectFlags.Depth;
            }
            else
            {
                aspectFlags = VkImageAspectFlags.Color;
            }

            imageViewCI.subresourceRange = new VkImageSubresourceRange(
                aspectFlags,
                description.BaseMipLevel,
                description.MipLevels,
                description.BaseArrayLayer,
                description.ArrayLayers);

            if ((tex.Usage & TextureUsage.Cubemap) == TextureUsage.Cubemap)
            {
                imageViewCI.viewType = description.ArrayLayers == 1 ? VkImageViewType.ImageCube : VkImageViewType.ImageCubeArray;
                imageViewCI.subresourceRange.layerCount *= 6;
            }
            else if (tex.Depth == 1)
            {
                imageViewCI.viewType = description.ArrayLayers == 1 ? VkImageViewType.Image2D : VkImageViewType.Image2DArray;
            }
            else
            {
                imageViewCI.viewType = VkImageViewType.Image3D;
            }

            vkCreateImageView(_gd.Device, ref imageViewCI, null, out _imageView);
        }
Ejemplo n.º 15
0
        private void CreateFramebuffers()
        {
            if (_scFramebuffers != null)
            {
                for (int i = 0; i < _scFramebuffers.Length; i++)
                {
                    _scFramebuffers[i]?.Dispose();
                    _scFramebuffers[i] = null;
                }
                Array.Clear(_scFramebuffers, 0, _scFramebuffers.Length);
            }

            EnsureSize(ref _scFramebuffers, _scImages.Length);
            EnsureSize(ref _scColorTextures, _scImages.Length);
            for (uint i = 0; i < _scImages.Length; i++)
            {
                VkTexture colorTex          = new VkTexture(_gd, _scExtent.width, _scExtent.height, 1, 1, _scImageFormat, TextureUsage.RenderTarget, _scImages[i]);
                FramebufferDescription desc = new FramebufferDescription(_depthTexture, colorTex);
                VkFramebuffer          fb   = (VkFramebuffer)_gd.ResourceFactory.CreateFramebuffer(ref desc);
                _scFramebuffers[i]  = fb;
                _scColorTextures[i] = new VkTexture[] { colorTex };
            }
        }
Ejemplo n.º 16
0
        private void BeginCurrentRenderPass()
        {
            Debug.Assert(_activeRenderPass == VkRenderPass.Null);
            Debug.Assert(_currentFramebuffer != null);
            _currentFramebufferEverActive = true;

            uint attachmentCount    = _currentFramebuffer.AttachmentCount;
            bool haveAnyAttachments = _framebuffer.ColorTargets.Count > 0 || _framebuffer.DepthTarget != null;
            bool haveAllClearValues = _depthClearValue.HasValue || _framebuffer.DepthTarget == null;
            bool haveAnyClearValues = _depthClearValue.HasValue;

            for (int i = 0; i < _currentFramebuffer.ColorTargets.Count; i++)
            {
                if (!_validColorClearValues[i])
                {
                    haveAllClearValues = false;
                    haveAnyClearValues = true;
                }
                else
                {
                    haveAnyClearValues = true;
                }
            }

            VkRenderPassBeginInfo renderPassBI = VkRenderPassBeginInfo.New();

            renderPassBI.renderArea  = new VkRect2D(_currentFramebuffer.RenderableWidth, _currentFramebuffer.RenderableHeight);
            renderPassBI.framebuffer = _currentFramebuffer.CurrentFramebuffer;

            if (!haveAnyAttachments || !haveAllClearValues)
            {
                renderPassBI.renderPass = _currentFramebuffer.RenderPassNoClear;
                vkCmdBeginRenderPass(_cb, ref renderPassBI, VkSubpassContents.Inline);
                _activeRenderPass = _currentFramebuffer.RenderPassNoClear;

                if (haveAnyClearValues)
                {
                    if (_depthClearValue.HasValue)
                    {
                        ClearDepthStencil(_depthClearValue.Value.depthStencil.depth, (byte)_depthClearValue.Value.depthStencil.stencil);
                        _depthClearValue = null;
                    }

                    for (uint i = 0; i < _currentFramebuffer.ColorTargets.Count; i++)
                    {
                        if (_validColorClearValues[i])
                        {
                            _validColorClearValues[i] = false;
                            VkClearValue vkClearValue = _clearValues[i];
                            RgbaFloat    clearColor   = new RgbaFloat(
                                vkClearValue.color.float32_0,
                                vkClearValue.color.float32_1,
                                vkClearValue.color.float32_2,
                                vkClearValue.color.float32_3);
                            ClearColorTarget(i, clearColor);
                        }
                    }
                }
            }
            else
            {
                // We have clear values for every attachment.
                renderPassBI.renderPass = _currentFramebuffer.RenderPassClear;
                fixed(VkClearValue *clearValuesPtr = &_clearValues[0])
                {
                    renderPassBI.clearValueCount = attachmentCount;
                    renderPassBI.pClearValues    = clearValuesPtr;
                    if (_depthClearValue.HasValue)
                    {
                        _clearValues[_currentFramebuffer.ColorTargets.Count] = _depthClearValue.Value;
                    }
                    vkCmdBeginRenderPass(_cb, ref renderPassBI, VkSubpassContents.Inline);
                    _activeRenderPass = _currentFramebuffer.RenderPassClear;
                    Util.ClearArray(_validColorClearValues);
                }
            }

            // Set new image layouts
            foreach (FramebufferAttachment colorTarget in _currentFramebuffer.ColorTargets)
            {
                VkTexture     vkTex  = Util.AssertSubtype <Texture, VkTexture>(colorTarget.Target);
                VkImageLayout layout = (vkTex.Usage & TextureUsage.Sampled) != 0
                    ? VkImageLayout.ShaderReadOnlyOptimal
                    : VkImageLayout.ColorAttachmentOptimal;
                vkTex.SetImageLayout(colorTarget.ArrayLayer, layout);
            }

            if (_currentFramebuffer.DepthTarget != null)
            {
                VkTexture     vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(_currentFramebuffer.DepthTarget.Value.Target);
                VkImageLayout layout     = (vkDepthTex.Usage & TextureUsage.Sampled) != 0
                    ? VkImageLayout.ShaderReadOnlyOptimal
                    : VkImageLayout.DepthStencilAttachmentOptimal;

                vkDepthTex.SetImageLayout(_currentFramebuffer.DepthTarget.Value.ArrayLayer, layout);
            }
        }
Ejemplo n.º 17
0
        internal static void CopyTextureCore_VkCommandBuffer(
            VkCommandBuffer cb,
            Texture source,
            uint srcX, uint srcY, uint srcZ,
            uint srcMipLevel,
            uint srcBaseArrayLayer,
            Texture destination,
            uint dstX, uint dstY, uint dstZ,
            uint dstMipLevel,
            uint dstBaseArrayLayer,
            uint width, uint height, uint depth,
            uint layerCount)
        {
            VkTexture srcVkTexture = Util.AssertSubtype <Texture, VkTexture>(source);
            VkTexture dstVkTexture = Util.AssertSubtype <Texture, VkTexture>(destination);

            bool sourceIsStaging = (source.Usage & TextureUsage.Staging) == TextureUsage.Staging;
            bool destIsStaging   = (destination.Usage & TextureUsage.Staging) == TextureUsage.Staging;

            if (!sourceIsStaging && !destIsStaging)
            {
                VkImageSubresourceLayers srcSubresource = new VkImageSubresourceLayers
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    layerCount     = layerCount,
                    mipLevel       = srcMipLevel,
                    baseArrayLayer = srcBaseArrayLayer
                };

                VkImageSubresourceLayers dstSubresource = new VkImageSubresourceLayers
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    layerCount     = layerCount,
                    mipLevel       = dstMipLevel,
                    baseArrayLayer = dstBaseArrayLayer
                };

                VkImageCopy region = new VkImageCopy
                {
                    srcOffset = new VkOffset3D {
                        x = (int)srcX, y = (int)srcY, z = (int)srcZ
                    },
                    dstOffset = new VkOffset3D {
                        x = (int)dstX, y = (int)dstY, z = (int)dstZ
                    },
                    srcSubresource = srcSubresource,
                    dstSubresource = dstSubresource,
                    extent         = new VkExtent3D {
                        width = width, height = height, depth = depth
                    }
                };

                srcVkTexture.TransitionImageLayout(
                    cb,
                    srcMipLevel,
                    1,
                    srcBaseArrayLayer,
                    layerCount,
                    VkImageLayout.TransferSrcOptimal);

                dstVkTexture.TransitionImageLayout(
                    cb,
                    dstMipLevel,
                    1,
                    dstBaseArrayLayer,
                    layerCount,
                    VkImageLayout.TransferDstOptimal);

                vkCmdCopyImage(
                    cb,
                    srcVkTexture.OptimalDeviceImage,
                    VkImageLayout.TransferSrcOptimal,
                    dstVkTexture.OptimalDeviceImage,
                    VkImageLayout.TransferDstOptimal,
                    1,
                    ref region);
            }
            else if (sourceIsStaging && !destIsStaging)
            {
                Vulkan.VkBuffer     srcBuffer = srcVkTexture.StagingBuffer;
                VkSubresourceLayout srcLayout = srcVkTexture.GetSubresourceLayout(
                    srcVkTexture.CalculateSubresource(srcMipLevel, srcBaseArrayLayer));
                VkImage dstImage = dstVkTexture.OptimalDeviceImage;
                dstVkTexture.TransitionImageLayout(
                    cb,
                    dstMipLevel,
                    1,
                    dstBaseArrayLayer,
                    layerCount,
                    VkImageLayout.TransferDstOptimal);

                VkImageSubresourceLayers dstSubresource = new VkImageSubresourceLayers
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    layerCount     = layerCount,
                    mipLevel       = dstMipLevel,
                    baseArrayLayer = dstBaseArrayLayer
                };

                Util.GetMipDimensions(srcVkTexture, srcMipLevel, out uint mipWidth, out uint mipHeight, out uint mipDepth);
                uint blockSize         = FormatHelpers.IsCompressedFormat(srcVkTexture.Format) ? 4u : 1u;
                uint bufferRowLength   = Math.Max(mipWidth, blockSize);
                uint bufferImageHeight = Math.Max(mipHeight, blockSize);
                uint compressedX       = srcX / blockSize;
                uint compressedY       = srcY / blockSize;
                uint blockSizeInBytes  = blockSize == 1
                    ? FormatHelpers.GetSizeInBytes(srcVkTexture.Format)
                    : FormatHelpers.GetBlockSizeInBytes(srcVkTexture.Format);
                uint rowPitch   = FormatHelpers.GetRowPitch(bufferRowLength, srcVkTexture.Format);
                uint depthPitch = FormatHelpers.GetDepthPitch(rowPitch, bufferImageHeight, srcVkTexture.Format);

                VkBufferImageCopy regions = new VkBufferImageCopy
                {
                    bufferOffset = srcLayout.offset
                                   + (srcZ * depthPitch)
                                   + (compressedY * rowPitch)
                                   + (compressedX * blockSizeInBytes),
                    bufferRowLength   = bufferRowLength,
                    bufferImageHeight = bufferImageHeight,
                    imageExtent       = new VkExtent3D {
                        width = width, height = height, depth = depth
                    },
                    imageOffset = new VkOffset3D {
                        x = (int)dstX, y = (int)dstY, z = (int)dstZ
                    },
                    imageSubresource = dstSubresource
                };

                vkCmdCopyBufferToImage(cb, srcBuffer, dstImage, VkImageLayout.TransferDstOptimal, 1, ref regions);
            }
            else if (!sourceIsStaging && destIsStaging)
            {
                VkImage srcImage = srcVkTexture.OptimalDeviceImage;
                srcVkTexture.TransitionImageLayout(
                    cb,
                    srcMipLevel,
                    1,
                    srcBaseArrayLayer,
                    layerCount,
                    VkImageLayout.TransferSrcOptimal);

                Vulkan.VkBuffer     dstBuffer = dstVkTexture.StagingBuffer;
                VkSubresourceLayout dstLayout = dstVkTexture.GetSubresourceLayout(
                    dstVkTexture.CalculateSubresource(dstMipLevel, dstBaseArrayLayer));
                VkImageSubresourceLayers srcSubresource = new VkImageSubresourceLayers
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    layerCount     = layerCount,
                    mipLevel       = srcMipLevel,
                    baseArrayLayer = srcBaseArrayLayer
                };

                Util.GetMipDimensions(dstVkTexture, dstMipLevel, out uint mipWidth, out uint mipHeight, out uint mipDepth);
                VkBufferImageCopy region = new VkBufferImageCopy
                {
                    bufferRowLength   = mipWidth,
                    bufferImageHeight = mipHeight,
                    bufferOffset      = dstLayout.offset + (dstX * FormatHelpers.GetSizeInBytes(dstVkTexture.Format)),
                    imageExtent       = new VkExtent3D {
                        width = width, height = height, depth = depth
                    },
                    imageOffset = new VkOffset3D {
                        x = (int)dstX, y = (int)dstY, z = (int)dstZ
                    },
                    imageSubresource = srcSubresource
                };

                vkCmdCopyImageToBuffer(cb, srcImage, VkImageLayout.TransferSrcOptimal, dstBuffer, 1, ref region);
            }
            else
            {
                Debug.Assert(sourceIsStaging && destIsStaging);
                Vulkan.VkBuffer     srcBuffer = srcVkTexture.StagingBuffer;
                VkSubresourceLayout srcLayout = srcVkTexture.GetSubresourceLayout(
                    srcVkTexture.CalculateSubresource(srcMipLevel, srcBaseArrayLayer));
                Vulkan.VkBuffer     dstBuffer = dstVkTexture.StagingBuffer;
                VkSubresourceLayout dstLayout = dstVkTexture.GetSubresourceLayout(
                    dstVkTexture.CalculateSubresource(dstMipLevel, dstBaseArrayLayer));

                uint zLimit = Math.Max(depth, layerCount);
                if (!FormatHelpers.IsCompressedFormat(source.Format))
                {
                    uint pixelSize = FormatHelpers.GetSizeInBytes(srcVkTexture.Format);
                    for (uint zz = 0; zz < zLimit; zz++)
                    {
                        for (uint yy = 0; yy < height; yy++)
                        {
                            VkBufferCopy region = new VkBufferCopy
                            {
                                srcOffset = srcLayout.offset
                                            + srcLayout.depthPitch * (zz + srcZ)
                                            + srcLayout.rowPitch * (yy + srcY)
                                            + pixelSize * srcX,
                                dstOffset = dstLayout.offset
                                            + dstLayout.depthPitch * (zz + dstZ)
                                            + dstLayout.rowPitch * (yy + dstY)
                                            + pixelSize * dstX,
                                size = width * pixelSize,
                            };

                            vkCmdCopyBuffer(cb, srcBuffer, dstBuffer, 1, ref region);
                        }
                    }
                }
                else // IsCompressedFormat
                {
                    uint denseRowSize     = FormatHelpers.GetRowPitch(width, source.Format);
                    uint numRows          = FormatHelpers.GetNumRows(height, source.Format);
                    uint compressedSrcX   = srcX / 4;
                    uint compressedSrcY   = srcY / 4;
                    uint compressedDstX   = dstX / 4;
                    uint compressedDstY   = dstY / 4;
                    uint blockSizeInBytes = FormatHelpers.GetBlockSizeInBytes(source.Format);

                    for (uint zz = 0; zz < zLimit; zz++)
                    {
                        for (uint row = 0; row < numRows; row++)
                        {
                            VkBufferCopy region = new VkBufferCopy
                            {
                                srcOffset = srcLayout.offset
                                            + srcLayout.depthPitch * (zz + srcZ)
                                            + srcLayout.rowPitch * (row + compressedSrcY)
                                            + blockSizeInBytes * compressedSrcX,
                                dstOffset = dstLayout.offset
                                            + dstLayout.depthPitch * (zz + dstZ)
                                            + dstLayout.rowPitch * (row + compressedDstY)
                                            + blockSizeInBytes * compressedDstX,
                                size = denseRowSize,
                            };

                            vkCmdCopyBuffer(cb, srcBuffer, dstBuffer, 1, ref region);
                        }
                    }
                }
            }
        }
Ejemplo n.º 18
0
        public VkFramebuffer(VkGraphicsDevice gd, ref FramebufferDescription description, bool isPresented)
            : base(description.DepthTarget, description.ColorTargets)
        {
            _gd = gd;

            VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New();

            StackList <VkAttachmentDescription> attachments = new StackList <VkAttachmentDescription>();

            uint colorAttachmentCount = (uint)ColorTargets.Count;
            StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>();

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                VkTexture vkColorTex = Util.AssertSubtype <Texture, VkTexture>(ColorTargets[i].Target);
                VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription();
                colorAttachmentDesc.format         = vkColorTex.VkFormat;
                colorAttachmentDesc.samples        = vkColorTex.VkSampleCount;
                colorAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                colorAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                colorAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
                colorAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                colorAttachmentDesc.finalLayout    = VkImageLayout.ColorAttachmentOptimal;
                attachments.Add(colorAttachmentDesc);

                VkAttachmentReference colorAttachmentRef = new VkAttachmentReference();
                colorAttachmentRef.attachment = (uint)i;
                colorAttachmentRef.layout     = VkImageLayout.ColorAttachmentOptimal;
                colorAttachmentRefs.Add(colorAttachmentRef);
            }

            VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription();
            VkAttachmentReference   depthAttachmentRef  = new VkAttachmentReference();

            if (DepthTarget != null)
            {
                VkTexture vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target);
                bool      hasStencil = FormatHelpers.IsStencilFormat(vkDepthTex.Format);
                depthAttachmentDesc.format         = vkDepthTex.VkFormat;
                depthAttachmentDesc.samples        = vkDepthTex.VkSampleCount;
                depthAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                depthAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.stencilStoreOp = hasStencil ? VkAttachmentStoreOp.Store : VkAttachmentStoreOp.DontCare;
                depthAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                depthAttachmentDesc.finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal;

                depthAttachmentRef.attachment = (uint)description.ColorTargets.Length;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();

            subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics;
            if (ColorTargets.Count > 0)
            {
                subpass.colorAttachmentCount = colorAttachmentCount;
                subpass.pColorAttachments    = (VkAttachmentReference *)colorAttachmentRefs.Data;
            }

            if (DepthTarget != null)
            {
                subpass.pDepthStencilAttachment = &depthAttachmentRef;
                attachments.Add(depthAttachmentDesc);
            }

            VkSubpassDependency subpassDependency = new VkSubpassDependency();

            subpassDependency.srcSubpass    = SubpassExternal;
            subpassDependency.srcStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite;
            if (DepthTarget != null)
            {
                subpassDependency.dstAccessMask |= VkAccessFlags.DepthStencilAttachmentRead | VkAccessFlags.DepthStencilAttachmentWrite;
            }

            renderPassCI.attachmentCount = attachments.Count;
            renderPassCI.pAttachments    = (VkAttachmentDescription *)attachments.Data;
            renderPassCI.subpassCount    = 1;
            renderPassCI.pSubpasses      = &subpass;
            renderPassCI.dependencyCount = 1;
            renderPassCI.pDependencies   = &subpassDependency;

            VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassNoClear);

            CheckResult(creationResult);

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                attachments[i].loadOp        = VkAttachmentLoadOp.Load;
                attachments[i].initialLayout = VkImageLayout.ColorAttachmentOptimal;
            }
            if (DepthTarget != null)
            {
                attachments[attachments.Count - 1].loadOp        = VkAttachmentLoadOp.Load;
                attachments[attachments.Count - 1].initialLayout = VkImageLayout.DepthStencilAttachmentOptimal;
                bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format);
                if (hasStencil)
                {
                    attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Load;
                }
            }
            creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassNoClearLoad);
            CheckResult(creationResult);


            // Load version

            if (DepthTarget != null)
            {
                attachments[attachments.Count - 1].loadOp        = VkAttachmentLoadOp.Clear;
                attachments[attachments.Count - 1].initialLayout = VkImageLayout.Undefined;
                bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format);
                if (hasStencil)
                {
                    attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Clear;
                }
            }

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                attachments[i].loadOp        = VkAttachmentLoadOp.Clear;
                attachments[i].initialLayout = VkImageLayout.Undefined;
            }

            creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassClear);
            CheckResult(creationResult);

            VkFramebufferCreateInfo fbCI = VkFramebufferCreateInfo.New();
            uint fbAttachmentsCount      = (uint)description.ColorTargets.Length;

            if (description.DepthTarget != null)
            {
                fbAttachmentsCount += 1;
            }

            VkImageView *fbAttachments = stackalloc VkImageView[(int)fbAttachmentsCount];

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                VkTexture             vkColorTarget = Util.AssertSubtype <Texture, VkTexture>(description.ColorTargets[i].Target);
                VkImageViewCreateInfo imageViewCI   = VkImageViewCreateInfo.New();
                imageViewCI.image            = vkColorTarget.OptimalDeviceImage;
                imageViewCI.format           = vkColorTarget.VkFormat;
                imageViewCI.viewType         = VkImageViewType.Image2D;
                imageViewCI.subresourceRange = new VkImageSubresourceRange(
                    VkImageAspectFlags.Color,
                    description.ColorTargets[i].MipLevel,
                    1,
                    description.ColorTargets[i].ArrayLayer,
                    1);
                VkImageView *dest   = (fbAttachments + i);
                VkResult     result = vkCreateImageView(_gd.Device, ref imageViewCI, null, dest);
                CheckResult(result);
                _attachmentViews.Add(*dest);
            }

            // Depth
            if (description.DepthTarget != null)
            {
                VkTexture             vkDepthTarget = Util.AssertSubtype <Texture, VkTexture>(description.DepthTarget.Value.Target);
                bool                  hasStencil    = FormatHelpers.IsStencilFormat(vkDepthTarget.Format);
                VkImageViewCreateInfo depthViewCI   = VkImageViewCreateInfo.New();
                depthViewCI.image            = vkDepthTarget.OptimalDeviceImage;
                depthViewCI.format           = vkDepthTarget.VkFormat;
                depthViewCI.viewType         = description.DepthTarget.Value.Target.ArrayLayers == 1 ? VkImageViewType.Image2D : VkImageViewType.Image2DArray;
                depthViewCI.subresourceRange = new VkImageSubresourceRange(
                    hasStencil ? VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil : VkImageAspectFlags.Depth,
                    description.DepthTarget.Value.MipLevel,
                    1,
                    description.DepthTarget.Value.ArrayLayer,
                    1);
                VkImageView *dest   = (fbAttachments + (fbAttachmentsCount - 1));
                VkResult     result = vkCreateImageView(_gd.Device, ref depthViewCI, null, dest);
                CheckResult(result);
                _attachmentViews.Add(*dest);
            }

            Texture dimTex;
            uint    mipLevel;

            if (ColorTargets.Count > 0)
            {
                dimTex   = ColorTargets[0].Target;
                mipLevel = ColorTargets[0].MipLevel;
            }
            else
            {
                Debug.Assert(DepthTarget != null);
                dimTex   = DepthTarget.Value.Target;
                mipLevel = DepthTarget.Value.MipLevel;
            }

            Util.GetMipDimensions(
                dimTex,
                mipLevel,
                out uint mipWidth,
                out uint mipHeight,
                out _);

            fbCI.width  = mipWidth;
            fbCI.height = mipHeight;

            fbCI.attachmentCount = fbAttachmentsCount;
            fbCI.pAttachments    = fbAttachments;
            fbCI.layers          = 1;
            fbCI.renderPass      = _renderPassNoClear;

            creationResult = vkCreateFramebuffer(_gd.Device, ref fbCI, null, out _deviceFramebuffer);
            CheckResult(creationResult);

            if (DepthTarget != null)
            {
                AttachmentCount += 1;
            }
            AttachmentCount += (uint)ColorTargets.Count;
        }
Ejemplo n.º 19
0
        public VkFramebuffer(VkGraphicsDevice gd, ref FramebufferDescription description)
            : base(description.DepthTarget, description.ColorTargets)
        {
            _gd = gd;

            VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New();

            StackList <VkAttachmentDescription> attachments = new StackList <VkAttachmentDescription>();

            uint colorAttachmentCount = (uint)ColorTextures.Count;
            StackList <VkAttachmentDescription> colorAttachmentDescriptions = new StackList <VkAttachmentDescription>();
            StackList <VkAttachmentReference>   colorAttachmentRefs         = new StackList <VkAttachmentReference>();

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                VkTexture vkColorTex = Util.AssertSubtype <Texture, VkTexture>(ColorTextures[i]);
                VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription();
                colorAttachmentDesc.format         = vkColorTex.VkFormat;
                colorAttachmentDesc.samples        = VkSampleCountFlags.Count1;
                colorAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                colorAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                colorAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
                colorAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                colorAttachmentDesc.finalLayout    = VkImageLayout.PresentSrcKHR;
                colorAttachmentDescriptions.Add(colorAttachmentDesc);
                attachments.Add(colorAttachmentDesc);

                VkAttachmentReference colorAttachmentRef = new VkAttachmentReference();
                colorAttachmentRef.attachment = (uint)i;
                colorAttachmentRef.layout     = VkImageLayout.ColorAttachmentOptimal;
                colorAttachmentRefs.Add(colorAttachmentRef);
            }

            VkTexture vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(DepthTexture);
            VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription();
            VkAttachmentReference   depthAttachmentRef  = new VkAttachmentReference();

            if (vkDepthTex != null)
            {
                depthAttachmentDesc.format         = vkDepthTex.VkFormat;
                depthAttachmentDesc.samples        = VkSampleCountFlags.Count1;
                depthAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                depthAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
                depthAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                depthAttachmentDesc.finalLayout    = VkImageLayout.ShaderReadOnlyOptimal;

                depthAttachmentRef.attachment = (uint)description.ColorTargets.Length;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();

            subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics;
            if (ColorTextures.Count > 0)
            {
                subpass.colorAttachmentCount = colorAttachmentCount;
                subpass.pColorAttachments    = (VkAttachmentReference *)colorAttachmentRefs.Data;
            }

            if (DepthTexture != null)
            {
                subpass.pDepthStencilAttachment = &depthAttachmentRef;
                attachments.Add(depthAttachmentDesc);
            }

            VkSubpassDependency subpassDependency = new VkSubpassDependency();

            subpassDependency.srcSubpass    = SubpassExternal;
            subpassDependency.srcStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite;
            if (DepthTexture != null)
            {
                subpassDependency.dstAccessMask |= VkAccessFlags.DepthStencilAttachmentRead | VkAccessFlags.DepthStencilAttachmentWrite;
            }

            renderPassCI.attachmentCount = attachments.Count;
            renderPassCI.pAttachments    = (VkAttachmentDescription *)attachments.Data;
            renderPassCI.subpassCount    = 1;
            renderPassCI.pSubpasses      = &subpass;
            renderPassCI.dependencyCount = 1;
            renderPassCI.pDependencies   = &subpassDependency;

            VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass);

            CheckResult(creationResult);

            VkFramebufferCreateInfo fbCI = VkFramebufferCreateInfo.New();
            uint fbAttachmentsCount      = (uint)description.ColorTargets.Length;

            if (description.DepthTarget != null)
            {
                fbAttachmentsCount += 1;
            }

            VkImageView *fbAttachments = stackalloc VkImageView[(int)fbAttachmentsCount];

            for (int i = 0; i < fbAttachmentsCount - 1; i++)
            {
                Texture               colorTarget   = description.ColorTargets[i];
                VkTexture             vkColorTarget = Util.AssertSubtype <Texture, VkTexture>(colorTarget);
                VkImageViewCreateInfo imageViewCI   = VkImageViewCreateInfo.New();
                imageViewCI.image            = vkColorTarget.DeviceImage;
                imageViewCI.format           = vkColorTarget.VkFormat;
                imageViewCI.viewType         = VkImageViewType.Image2D;
                imageViewCI.subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1);
                VkImageView *dest   = (fbAttachments + i);
                VkResult     result = vkCreateImageView(_gd.Device, ref imageViewCI, null, dest);
                CheckResult(result);
                _attachmentViews.Add(*dest);
            }

            // Depth
            if (description.DepthTarget != null)
            {
                VkTexture             vkDepthTarget = Util.AssertSubtype <Texture, VkTexture>(description.DepthTarget);
                VkImageViewCreateInfo depthViewCI   = VkImageViewCreateInfo.New();
                depthViewCI.image            = vkDepthTarget.DeviceImage;
                depthViewCI.format           = vkDepthTarget.VkFormat;
                depthViewCI.viewType         = VkImageViewType.Image2D;
                depthViewCI.subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Depth, 0, 1, 0, 1);
                VkImageView *dest   = (fbAttachments + (fbAttachmentsCount - 1));
                VkResult     result = vkCreateImageView(_gd.Device, ref depthViewCI, null, dest);
                CheckResult(result);
                _attachmentViews.Add(*dest);
            }

            if (ColorTextures.Count > 0)
            {
                fbCI.width  = ColorTextures[0].Width;
                fbCI.height = ColorTextures[0].Height;
            }
            else if (vkDepthTex != null)
            {
                fbCI.width  = vkDepthTex.Width;
                fbCI.height = vkDepthTex.Height;
            }

            fbCI.attachmentCount = fbAttachmentsCount;
            fbCI.pAttachments    = fbAttachments;
            fbCI.layers          = 1;
            fbCI.renderPass      = _renderPass;

            creationResult = vkCreateFramebuffer(_gd.Device, ref fbCI, null, out _deviceFramebuffer);
            CheckResult(creationResult);
        }
Ejemplo n.º 20
0
        protected override void CopyTextureCore(
            Texture source,
            uint srcX, uint srcY, uint srcZ,
            uint srcMipLevel,
            uint srcBaseArrayLayer,
            Texture destination,
            uint dstX, uint dstY, uint dstZ,
            uint dstMipLevel,
            uint dstBaseArrayLayer,
            uint width, uint height, uint depth,
            uint layerCount)
        {
            EnsureNoRenderPass();

            bool sourceIsStaging = (source.Usage & TextureUsage.Staging) == TextureUsage.Staging;
            bool destIsStaging   = (destination.Usage & TextureUsage.Staging) == TextureUsage.Staging;

            if ((destIsStaging || sourceIsStaging) && layerCount > 1)
            {
                // Need to issue one copy per array layer.
                throw new NotImplementedException();
            }

            VkImageSubresourceLayers srcSubresource = new VkImageSubresourceLayers
            {
                aspectMask     = VkImageAspectFlags.Color,
                layerCount     = layerCount,
                mipLevel       = sourceIsStaging ? 0 : srcMipLevel,
                baseArrayLayer = sourceIsStaging ? 0 : srcBaseArrayLayer
            };

            VkImageSubresourceLayers dstSubresource = new VkImageSubresourceLayers
            {
                aspectMask     = VkImageAspectFlags.Color,
                layerCount     = layerCount,
                mipLevel       = destIsStaging ? 0 : dstMipLevel,
                baseArrayLayer = destIsStaging ? 0 : dstBaseArrayLayer
            };

            VkImageCopy region = new VkImageCopy
            {
                srcOffset = new VkOffset3D {
                    x = (int)srcX, y = (int)srcY, z = (int)srcZ
                },
                dstOffset = new VkOffset3D {
                    x = (int)dstX, y = (int)dstY, z = (int)dstZ
                },
                srcSubresource = srcSubresource,
                dstSubresource = dstSubresource,
                extent         = new VkExtent3D {
                    width = width, height = height, depth = depth
                }
            };

            VkTexture srcVkTexture = Util.AssertSubtype <Texture, VkTexture>(source);
            VkTexture dstVkTexture = Util.AssertSubtype <Texture, VkTexture>(destination);

            srcVkTexture.TransitionImageLayout(
                _cb,
                srcMipLevel,
                1,
                srcBaseArrayLayer,
                layerCount,
                VkImageLayout.TransferSrcOptimal);

            dstVkTexture.TransitionImageLayout(
                _cb,
                dstMipLevel,
                1,
                dstBaseArrayLayer,
                layerCount,
                VkImageLayout.TransferDstOptimal);

            VkImage srcImage = sourceIsStaging
                ? srcVkTexture.GetStagingImage(source.CalculateSubresource(srcMipLevel, srcBaseArrayLayer))
                : srcVkTexture.OptimalDeviceImage;
            VkImage dstImage = destIsStaging
                ? dstVkTexture.GetStagingImage(destination.CalculateSubresource(dstMipLevel, dstBaseArrayLayer))
                : dstVkTexture.OptimalDeviceImage;

            vkCmdCopyImage(
                _cb,
                srcImage,
                VkImageLayout.TransferSrcOptimal,
                dstImage,
                VkImageLayout.TransferDstOptimal,
                1,
                ref region);

            _referencedResources.Add(srcVkTexture);
            _referencedResources.Add(dstVkTexture);
        }
Ejemplo n.º 21
0
        public override void UpdateTextureCube(
            Texture textureCube,
            IntPtr source,
            uint sizeInBytes,
            CubeFace face,
            uint x,
            uint y,
            uint width,
            uint height,
            uint mipLevel,
            uint arrayLayer)
        {
            VkTexture vkTexCube = Util.AssertSubtype <Texture, VkTexture>(textureCube);

            if (x != 0 || y != 0)
            {
                throw new NotImplementedException();
            }

            // First, create a staging texture.
            CreateImage(
                _gd.Device,
                _gd.PhysicalDeviceMemProperties,
                _gd.MemoryManager,
                width,
                height,
                1,
                1,
                VkFormats.VdToVkPixelFormat(vkTexCube.Format),
                VkImageTiling.Linear,
                VkImageUsageFlags.TransferSrc,
                VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                out VkImage stagingImage,
                out VkMemoryBlock stagingMemory);

            VkImageSubresource subresource = new VkImageSubresource();

            subresource.aspectMask = VkImageAspectFlags.Color;
            subresource.mipLevel   = 0;
            subresource.arrayLayer = 0;
            vkGetImageSubresourceLayout(_gd.Device, stagingImage, ref subresource, out VkSubresourceLayout stagingLayout);
            ulong rowPitch = stagingLayout.rowPitch;

            void *   mappedPtr;
            VkResult result = vkMapMemory(_gd.Device, stagingMemory.DeviceMemory, stagingMemory.Offset, stagingLayout.size, 0, &mappedPtr);

            CheckResult(result);

            if (rowPitch == width)
            {
                System.Buffer.MemoryCopy(source.ToPointer(), mappedPtr, sizeInBytes, sizeInBytes);
            }
            else
            {
                uint pixelSizeInBytes = FormatHelpers.GetSizeInBytes(vkTexCube.Format);
                for (uint yy = 0; yy < height; yy++)
                {
                    byte *dstRowStart = ((byte *)mappedPtr) + (rowPitch * yy);
                    byte *srcRowStart = ((byte *)source.ToPointer()) + (width * yy * pixelSizeInBytes);
                    Unsafe.CopyBlock(dstRowStart, srcRowStart, width * pixelSizeInBytes);
                }
            }

            vkUnmapMemory(_gd.Device, stagingMemory.DeviceMemory);

            uint cubeArrayLayer = GetArrayLayer(face);

            // TODO: These transitions are sub-optimal.
            TransitionImageLayout(stagingImage, 0, 1, 0, 1, VkImageLayout.Preinitialized, VkImageLayout.TransferSrcOptimal);
            TransitionImageLayout(vkTexCube.DeviceImage, 0, 1, 0, 6, vkTexCube.ImageLayouts[0], VkImageLayout.TransferDstOptimal);
            CopyImage(stagingImage, 0, vkTexCube.DeviceImage, mipLevel, width, height, cubeArrayLayer);
            TransitionImageLayout(vkTexCube.DeviceImage, 0, 1, 0, 6, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal);
            vkTexCube.ImageLayouts[0] = VkImageLayout.ShaderReadOnlyOptimal;

            if (_imagesToDestroy == null)
            {
                _imagesToDestroy = new List <VkImage>();
            }
            _imagesToDestroy.Add(stagingImage);

            if (_memoriesToFree == null)
            {
                _memoriesToFree = new List <VkMemoryBlock>();
            }
            _memoriesToFree.Add(stagingMemory);
        }