private void CreateDepthStencilBuffer() { var formats = new[] { SharpVulkan.Format.D32SFloatS8UInt, SharpVulkan.Format.D24UNormS8UInt, SharpVulkan.Format.D16UNormS8UInt }; depthStencilFormat = formats.First(format => { context.PhysicalDevice.GetFormatProperties(format, out var formatProperties); return((formatProperties.OptimalTilingFeatures & SharpVulkan.FormatFeatureFlags.DepthStencilAttachment) != 0); }); var tiling = SharpVulkan.ImageTiling.Optimal; var createInfo = new SharpVulkan.ImageCreateInfo { StructureType = SharpVulkan.StructureType.ImageCreateInfo, ImageType = SharpVulkan.ImageType.Image2D, Usage = SharpVulkan.ImageUsageFlags.DepthStencilAttachment, Format = depthStencilFormat, Extent = new SharpVulkan.Extent3D((uint)width, (uint)height, 1), MipLevels = 1, ArrayLayers = 1, Samples = SharpVulkan.SampleCountFlags.Sample1, SharingMode = SharpVulkan.SharingMode.Exclusive, Tiling = tiling, InitialLayout = SharpVulkan.ImageLayout.Undefined }; depthStencilBuffer = context.Device.CreateImage(ref createInfo); depthStencilMemory = context.MemoryAllocator.Allocate(depthStencilBuffer, SharpVulkan.MemoryPropertyFlags.DeviceLocal, tiling); var viewCreateInfo = new SharpVulkan.ImageViewCreateInfo { StructureType = SharpVulkan.StructureType.ImageViewCreateInfo, ViewType = SharpVulkan.ImageViewType.Image2D, Image = depthStencilBuffer, Format = depthStencilFormat, Components = SharpVulkan.ComponentMapping.Identity, SubresourceRange = new SharpVulkan.ImageSubresourceRange( SharpVulkan.ImageAspectFlags.Depth | SharpVulkan.ImageAspectFlags.Stencil) }; depthStencilView = context.Device.CreateImageView(ref viewCreateInfo); var memoryBarrier = new SharpVulkan.ImageMemoryBarrier { StructureType = SharpVulkan.StructureType.ImageMemoryBarrier, Image = depthStencilBuffer, OldLayout = SharpVulkan.ImageLayout.Undefined, NewLayout = SharpVulkan.ImageLayout.DepthStencilAttachmentOptimal, SourceAccessMask = SharpVulkan.AccessFlags.None, DestinationAccessMask = SharpVulkan.AccessFlags.DepthStencilAttachmentRead | SharpVulkan.AccessFlags.DepthStencilAttachmentWrite, SubresourceRange = new SharpVulkan.ImageSubresourceRange( SharpVulkan.ImageAspectFlags.Depth | SharpVulkan.ImageAspectFlags.Stencil) }; context.EndRenderPass(); context.EnsureCommandBuffer(); context.CommandBuffer.PipelineBarrier(SharpVulkan.PipelineStageFlags.TopOfPipe, SharpVulkan.PipelineStageFlags.EarlyFragmentTests | SharpVulkan.PipelineStageFlags.LateFragmentTests, SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier); }
internal void GetData(Format dstFormat, int level, int x, int y, int width, int height, IntPtr data) { if (IsPvrtc1Format(Format)) { throw new NotImplementedException(); } var dataSize = GraphicsUtility.CalculateImageDataSize(Format, width, height); context.EnsureReadbackBuffer((ulong)dataSize); context.EndRenderPass(); context.EnsureCommandBuffer(); var preMemoryBarrier = new SharpVulkan.ImageMemoryBarrier { StructureType = SharpVulkan.StructureType.ImageMemoryBarrier, Image = image, OldLayout = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal, NewLayout = SharpVulkan.ImageLayout.TransferSourceOptimal, SourceAccessMask = SharpVulkan.AccessFlags.ShaderRead, DestinationAccessMask = SharpVulkan.AccessFlags.TransferRead, SubresourceRange = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level, 1) }; context.CommandBuffer.PipelineBarrier( SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader, SharpVulkan.PipelineStageFlags.Transfer, SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &preMemoryBarrier); var copyRegion = new SharpVulkan.BufferImageCopy { BufferOffset = 0, BufferRowLength = (uint)width, BufferImageHeight = (uint)height, ImageOffset = new SharpVulkan.Offset3D(x, y, 0), ImageExtent = new SharpVulkan.Extent3D((uint)width, (uint)height, 1), ImageSubresource = new SharpVulkan.ImageSubresourceLayers(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level) }; context.CommandBuffer.CopyImageToBuffer( image, SharpVulkan.ImageLayout.TransferSourceOptimal, context.ReadbackBuffer, 1, ©Region); var postMemoryBarrier = new SharpVulkan.ImageMemoryBarrier { StructureType = SharpVulkan.StructureType.ImageMemoryBarrier, Image = image, OldLayout = SharpVulkan.ImageLayout.TransferSourceOptimal, NewLayout = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal, SourceAccessMask = SharpVulkan.AccessFlags.TransferRead, DestinationAccessMask = SharpVulkan.AccessFlags.ShaderRead, SubresourceRange = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level, 1) }; context.CommandBuffer.PipelineBarrier( SharpVulkan.PipelineStageFlags.Transfer, SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader, SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &postMemoryBarrier); context.Finish(); var readbackBufferMemory = context.ReadbackBufferMemory; var readbackBufferMappedMemory = context.MemoryAllocator.Map(readbackBufferMemory); try { context.MemoryAllocator.InvalidateMappedMemoryRange(readbackBufferMemory, 0, (ulong)dataSize); if (dstFormat == Format) { GraphicsUtility.CopyMemory(data, readbackBufferMappedMemory, Format.GetSize() * width * height); } else { var decoder = FormatConverter.GetDecoder(Format); var encoder = FormatConverter.GetEncoder(dstFormat); var srcTexelSize = Format.GetSize(); var dstTexelSize = dstFormat.GetSize(); var srcData = readbackBufferMappedMemory; var dstData = data; var texelCount = width * height; while (texelCount-- > 0) { encoder(dstData, decoder(srcData)); srcData += srcTexelSize; dstData += dstTexelSize; } } } finally { context.MemoryAllocator.Unmap(readbackBufferMemory); } }
private void Create(bool renderTarget) { var vkFormat = VulkanHelper.GetVKFormat(format); var usage = SharpVulkan.ImageUsageFlags.TransferSource | SharpVulkan.ImageUsageFlags.TransferDestination | SharpVulkan.ImageUsageFlags.Sampled; if (renderTarget) { usage |= SharpVulkan.ImageUsageFlags.ColorAttachment; } var tiling = SharpVulkan.ImageTiling.Optimal; var imageCreateInfo = new SharpVulkan.ImageCreateInfo { StructureType = SharpVulkan.StructureType.ImageCreateInfo, ImageType = SharpVulkan.ImageType.Image2D, Usage = usage, Format = vkFormat, Extent = new SharpVulkan.Extent3D((uint)width, (uint)height, 1), MipLevels = (uint)levelCount, ArrayLayers = 1, Samples = SharpVulkan.SampleCountFlags.Sample1, SharingMode = SharpVulkan.SharingMode.Exclusive, InitialLayout = SharpVulkan.ImageLayout.Undefined, Tiling = tiling }; image = context.Device.CreateImage(ref imageCreateInfo); var memoryPropertyFlags = SharpVulkan.MemoryPropertyFlags.DeviceLocal; if (IsPvrtc1Format(Format)) { memoryPropertyFlags |= SharpVulkan.MemoryPropertyFlags.HostVisible | SharpVulkan.MemoryPropertyFlags.HostCoherent; } memory = context.MemoryAllocator.Allocate(image, memoryPropertyFlags, tiling); var viewCreateInfo = new SharpVulkan.ImageViewCreateInfo { StructureType = SharpVulkan.StructureType.ImageViewCreateInfo, ViewType = SharpVulkan.ImageViewType.Image2D, Image = image, Format = vkFormat, Components = SharpVulkan.ComponentMapping.Identity, SubresourceRange = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color) }; imageView = context.Device.CreateImageView(ref viewCreateInfo); var memoryBarrier = new SharpVulkan.ImageMemoryBarrier { StructureType = SharpVulkan.StructureType.ImageMemoryBarrier, Image = image, OldLayout = SharpVulkan.ImageLayout.Undefined, NewLayout = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal, SourceAccessMask = SharpVulkan.AccessFlags.None, DestinationAccessMask = SharpVulkan.AccessFlags.ShaderRead, SubresourceRange = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color) }; context.EndRenderPass(); context.EnsureCommandBuffer(); context.CommandBuffer.PipelineBarrier( SharpVulkan.PipelineStageFlags.TopOfPipe, SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader, SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier); }
public void SetData(int level, int x, int y, int width, int height, IntPtr data) { var dataSize = GraphicsUtility.CalculateImageDataSize(Format, width, height); if (IsPvrtc1Format(Format)) { if (x != 0 || y != 0 || width != Width || height != Height) { throw new NotSupportedException(); } if (context.NextFenceValue <= WriteFenceValue) { context.Flush(); } context.WaitForFence(WriteFenceValue); var dstData = Context.MemoryAllocator.Map(memory); try { GraphicsUtility.CopyMemory(dstData, data, dataSize); } finally { Context.MemoryAllocator.Unmap(memory); } } else { ulong bufferOffsetAlignment = 4; bufferOffsetAlignment = GraphicsUtility.CombineAlignment(bufferOffsetAlignment, (ulong)Format.GetSize()); bufferOffsetAlignment = GraphicsUtility.CombineAlignment(bufferOffsetAlignment, context.PhysicalDeviceLimits.OptimalBufferCopyOffsetAlignment); var uploadBufferAlloc = context.AllocateUploadBuffer((ulong)dataSize, bufferOffsetAlignment); GraphicsUtility.CopyMemory(uploadBufferAlloc.Data, data, dataSize); context.EndRenderPass(); context.EnsureCommandBuffer(); var preMemoryBarrier = new SharpVulkan.ImageMemoryBarrier { StructureType = SharpVulkan.StructureType.ImageMemoryBarrier, Image = image, OldLayout = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal, NewLayout = SharpVulkan.ImageLayout.TransferDestinationOptimal, SourceAccessMask = SharpVulkan.AccessFlags.ShaderRead, DestinationAccessMask = SharpVulkan.AccessFlags.TransferWrite, SubresourceRange = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level, 1) }; context.CommandBuffer.PipelineBarrier( SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader, SharpVulkan.PipelineStageFlags.Transfer, SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &preMemoryBarrier); var copyRegion = new SharpVulkan.BufferImageCopy { BufferOffset = uploadBufferAlloc.BufferOffset, BufferRowLength = (uint)width, BufferImageHeight = (uint)height, ImageOffset = new SharpVulkan.Offset3D(x, y, 0), ImageExtent = new SharpVulkan.Extent3D((uint)width, (uint)height, 1), ImageSubresource = new SharpVulkan.ImageSubresourceLayers(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level) }; context.CommandBuffer.CopyBufferToImage( uploadBufferAlloc.Buffer, image, SharpVulkan.ImageLayout.TransferDestinationOptimal, 1, ©Region); var postMemoryBarrier = new SharpVulkan.ImageMemoryBarrier { StructureType = SharpVulkan.StructureType.ImageMemoryBarrier, Image = image, OldLayout = SharpVulkan.ImageLayout.TransferDestinationOptimal, NewLayout = SharpVulkan.ImageLayout.ShaderReadOnlyOptimal, SourceAccessMask = SharpVulkan.AccessFlags.TransferWrite, DestinationAccessMask = SharpVulkan.AccessFlags.ShaderRead, SubresourceRange = new SharpVulkan.ImageSubresourceRange(SharpVulkan.ImageAspectFlags.Color, 0, 1, (uint)level, 1) }; context.CommandBuffer.PipelineBarrier( SharpVulkan.PipelineStageFlags.Transfer, SharpVulkan.PipelineStageFlags.VertexShader | SharpVulkan.PipelineStageFlags.FragmentShader, SharpVulkan.DependencyFlags.None, 0, null, 0, null, 1, &postMemoryBarrier); } }