コード例 #1
0
 /// <summary>
 /// Create a frame buffer for an attachment image
 /// </summary>
 /// <param name="image"></param>
 /// <returns></returns>
 public Framebuffer CreateFramebuffer(VKImage image)
 {
     // Check arguments
     if (image is null)
     {
         throw new ArgumentNullException(nameof(image));
     }
     // Create framebuffer
     return(RenderPass.CreateFramebuffer(new FramebufferCreateInfo(
                                             new[] { image.ImageView }, image.Extent.Width, image.Extent.Height
                                             )));
 }
コード例 #2
0
 /// <summary>
 /// Get the command buffer created for a registered image
 /// </summary>
 /// <param name="image"></param>
 /// <returns></returns>
 public CommandBuffer GetCommandBuffer(VKImage image)
 {
     // Check arguments
     if (image is null)
     {
         throw new ArgumentNullException(nameof(image));
     }
     if (CommandBuffers.TryGetValue(image, out var buffer))
     {
         return(buffer);
     }
     return(RegisterImage(image));
 }
コード例 #3
0
 /// <summary>
 /// Draw the effect
 /// </summary>
 public void Draw(Semaphore start, VKImage image)
 {
     // Check if disposed
     if (Disposed)
     {
         throw new ObjectDisposedException(Name);
     }
     // Make sure this effect is active
     if (!Active)
     {
         throw new InvalidOperationException("Effect is not active");
     }
     // Call OnDraw
     OnDraw(start, image);
 }
コード例 #4
0
 /// <summary>
 /// Unregister an image from the effect
 /// </summary>
 /// <param name="image"></param>
 public void UnregisterImage(VKImage image)
 {
     // Check arguments
     if (image is null)
     {
         throw new ArgumentNullException(nameof(image));
     }
     // Check if active
     if (!Active)
     {
         throw new InvalidOperationException("Effect is not active");
     }
     // Call OnUnregisterImage and unregister command buffer
     Graphics.Device.WaitIdle();
     OnUnregisterImage(image);
     CommandBuffers[image].Dispose();
     CommandBuffers.Remove(image);
 }
コード例 #5
0
        /// <summary>
        /// Register an image for rendering to
        /// </summary>
        /// <param name="image"></param>
        public CommandBuffer RegisterImage(VKImage image)
        {
            // Check arguments
            if (image is null)
            {
                throw new ArgumentNullException(nameof(image));
            }
            // Check if active
            if (!Active)
            {
                throw new InvalidOperationException("Effect is not active");
            }
            // Create new command buffer, register the image, and reord the command buffer
            var cmd = Graphics.GraphicsQueueFamily.CreateCommandBuffers(CommandBufferLevel.Primary, 1)[0];

            CommandBuffers.Add(image, cmd);
            OnRegisterImage(image);
            OnRecordCommandBuffer(image, cmd);
            return(cmd);
        }
コード例 #6
0
 /// <summary>
 /// Called when registering an image
 /// </summary>
 /// <param name="image"></param>
 protected virtual void OnUnregisterImage(VKImage image)
 {
 }
コード例 #7
0
 /// <summary>
 /// Called to record to a command buffer
 /// </summary>
 /// <param name="image"></param>
 /// <param name="buffer"></param>
 protected virtual void OnRecordCommandBuffer(VKImage image, CommandBuffer buffer)
 {
 }
コード例 #8
0
 /// <summary>
 /// Called when drawing the effect
 /// </summary>
 public virtual void OnDraw(Semaphore start, VKImage image = null)
 {
 }
コード例 #9
0
        public Texture2D(
            string name, Graphics graphics, TextureData2D data, bool premultiply = true
            )
        {
            Name     = name;
            Graphics = graphics;

            // Create image
            var image = Graphics.Device.CreateImage(new ImageCreateInfo
            {
                ImageType     = ImageType.Image2D,
                Format        = data.Format,
                MipLevels     = data.MipMaps.Length,
                ArrayLayers   = 1,
                Samples       = SampleCounts.Count1,
                Tiling        = ImageTiling.Optimal,
                SharingMode   = SharingMode.Exclusive,
                InitialLayout = ImageLayout.Undefined,
                Extent        = new Extent3D(data.MipMaps[0].Extent.Width, data.MipMaps[0].Extent.Height, 1),
                Usage         = ImageUsages.Sampled | ImageUsages.TransferDst
            });

            Image = new VKImage(
                image, data.Format, data.MipMaps[0].Extent,
                new ImageSubresourceRange(ImageAspects.Color, 0, data.MipMaps.Length, 0, 1
                                          ));
            var memReq = Image.Image.GetMemoryRequirements();

            DeviceMemory = Graphics.Device.AllocateMemory(new MemoryAllocateInfo(
                                                              allocationSize: memReq.Size,
                                                              memoryTypeIndex: Graphics.GetMemoryTypeIndex(memReq.MemoryTypeBits, MemoryProperties.DeviceLocal)
                                                              ));
            Image.Image.BindMemory(DeviceMemory);

            // Copy data to staging buffer
            var staging = VKBuffer <byte> .StagingBuffer($"{nameof(Texture2D)} staging buffer", Graphics, data.Size);

            unsafe
            {
                var dest = staging.Map(0, data.Size);
                foreach (var mip in data.MipMaps)
                {
                    fixed(byte *src = mip.Data)
                    {
                        if (premultiply)
                        {
                            switch (data.Format)
                            {
                            default:
                                throw new NotImplementedException(
                                          $"Premultiplying is not implemented for format: {data.Format}"
                                          );

                            case Format.B8G8R8A8UNorm:
                                for (var i = 0; i < mip.Size; i += 4)
                                {
                                    var b = src[i];
                                    var g = src[i + 1];
                                    var r = src[i + 2];
                                    var a = src[i + 3];
                                    b           = (byte)(b * (a / 255f));
                                    g           = (byte)(g * (a / 255f));
                                    r           = (byte)(r * (a / 255f));
                                    dest[i]     = b;
                                    dest[i + 1] = g;
                                    dest[i + 2] = r;
                                    dest[i + 3] = a;
                                }
                                break;
                            }
                        }
                        else
                        {
                            System.Buffer.MemoryCopy(src, dest, mip.Size, mip.Size);
                        }
                        dest += mip.Size;
                    }
                }
                staging.Unmap();
            }

            // Create copy regions
            var regions = new BufferImageCopy[data.MipMaps.Length];
            var offset  = 0L;

            for (var i = 0; i < regions.Length; i++)
            {
                regions[i] = new BufferImageCopy
                {
                    ImageSubresource = new ImageSubresourceLayers(ImageAspects.Color, i, 0, 1),
                    ImageExtent      = new Extent3D(data.MipMaps[0].Extent.Width, data.MipMaps[0].Extent.Height, 1),
                    BufferOffset     = offset
                };
                offset += data.MipMaps[i].Size;
            }

            // Create command buffer
            var range  = new ImageSubresourceRange(ImageAspects.Color, 0, data.MipMaps.Length, 0, 1);
            var buffer = Graphics.TransferQueueFamily.CreateCommandBuffers(CommandBufferLevel.Primary, 1)[0];

            buffer.Begin(new CommandBufferBeginInfo(CommandBufferUsages.OneTimeSubmit));
            buffer.CmdPipelineBarrier(
                PipelineStages.TopOfPipe, PipelineStages.Transfer,
                imageMemoryBarriers: new ImageMemoryBarrier[]
            {
                new ImageMemoryBarrier(
                    Image.Image, range,
                    Accesses.None, Accesses.TransferWrite,
                    ImageLayout.Undefined, ImageLayout.TransferDstOptimal
                    )
            }
                );
            buffer.CmdCopyBufferToImage(staging.Buffer, Image.Image, ImageLayout.TransferDstOptimal, regions);
            buffer.CmdPipelineBarrier(
                PipelineStages.Transfer, PipelineStages.FragmentShader,
                imageMemoryBarriers: new ImageMemoryBarrier[]
            {
                new ImageMemoryBarrier(
                    Image.Image, range,
                    Accesses.TransferWrite, Accesses.ShaderRead,
                    ImageLayout.TransferDstOptimal, ImageLayout.ShaderReadOnlyOptimal
                    )
            }
                );
            buffer.End();

            // Submit the buffer
            var fence = Graphics.Device.CreateFence(new FenceCreateInfo());

            Graphics.GraphicsQueueFamily.HighestPriority.Submit(
                new SubmitInfo(
                    commandBuffers: new CommandBuffer[] { buffer }
                    ),
                fence
                );
            fence.Wait();

            // Clean up
            fence.Dispose();
            staging.Dispose();
        }