public unsafe static Texture Create2D(uint w, uint h, VkFormat format, IntPtr tex2DDataPtr, bool dynamic = false) { var texture = new Texture { extent = new VkExtent3D(w, h, 1), mipLevels = 1, format = format }; texture.image = Image.Create(w, h, VkImageCreateFlags.None, 1, 1, format, VkSampleCountFlags.Count1, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled); ulong totalBytes = texture.image.AllocationSize; using (Buffer stagingBuffer = Buffer.CreateStagingBuffer(totalBytes, tex2DDataPtr)) { VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy { imageSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.Color, mipLevel = 0, baseArrayLayer = 0, layerCount = 1, }, imageExtent = new VkExtent3D(w, h, 1), bufferOffset = 0 }; // The sub resource range describes the regions of the image we will be transition var subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1); CommandBuffer copyCmd = Graphics.BeginPrimaryCmd(); copyCmd.SetImageLayout(texture.image, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subresourceRange); copyCmd.CopyBufferToImage(stagingBuffer, texture.image, VkImageLayout.TransferDstOptimal, ref bufferCopyRegion); copyCmd.SetImageLayout(texture.image, VkImageAspectFlags.Color, VkImageLayout.TransferDstOptimal, texture.imageLayout, subresourceRange); Graphics.EndPrimaryCmd(copyCmd); // Change texture image layout to shader read after all mip levels have been copied texture.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; } texture.imageView = ImageView.Create(texture.image, VkImageViewType.Image2D, format, VkImageAspectFlags.Color, 0, texture.mipLevels); texture.sampler = new Sampler(VkFilter.Linear, VkSamplerMipmapMode.Linear, VkSamplerAddressMode.Repeat, texture.mipLevels, Device.Features.samplerAnisotropy == true); texture.UpdateDescriptor(); return(texture); }
public unsafe void SetImageData(MipmapLevel[] imageData) { this.imageData = imageData; this.extent = new VkExtent3D(imageData[0].Width, imageData[0].Height, 1); mipLevels = (uint)imageData.Length; layers = (uint)imageData[0].ArrayElements.Length; faceCount = (uint)imageData[0].ArrayElements[0].Faces.Length; ulong totalSize = 0; foreach (var mip in imageData) { totalSize += mip.TotalSize * layers * faceCount; } Buffer stagingBuffer = Buffer.CreateStagingBuffer(totalSize, IntPtr.Zero); image = Image.Create(width, height, imageCreateFlags, layers * faceCount, mipLevels, format, VkSampleCountFlags.Count1, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled); IntPtr mapped = stagingBuffer.Map(); // Setup buffer copy regions for each face including all of it's miplevels Span <VkBufferImageCopy> bufferCopyRegions = stackalloc VkBufferImageCopy[(int)(mipLevels * layers * faceCount)]; uint offset = 0; int index = 0; for (int layer = 0; layer < layers; layer++) { for (int face = 0; face < faceCount; face++) { for (uint level = 0; level < mipLevels; level++) { var mipLevel = imageData[level]; var layerElement = mipLevel.ArrayElements[layer]; var faceElement = layerElement.Faces[face]; Unsafe.CopyBlock((void *)(mapped + (int)offset), Unsafe.AsPointer(ref faceElement.Data[0]), (uint)faceElement.Data.Length); VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy { imageSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.Color, mipLevel = level, baseArrayLayer = (uint)(layer * faceCount + face), layerCount = 1 }, imageExtent = new VkExtent3D(mipLevel.Width, mipLevel.Height, mipLevel.Depth), bufferOffset = offset }; bufferCopyRegions[index++] = bufferCopyRegion; offset += (uint)faceElement.Data.Length; } } } stagingBuffer.Unmap(); var subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, mipLevels, 0, layers * faceCount); CommandBuffer copyCmd = Graphics.BeginPrimaryCmd(); copyCmd.SetImageLayout(image, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subresourceRange); copyCmd.CopyBufferToImage(stagingBuffer, image, VkImageLayout.TransferDstOptimal, bufferCopyRegions); copyCmd.SetImageLayout(image, VkImageAspectFlags.Color, VkImageLayout.TransferDstOptimal, imageLayout, subresourceRange); Graphics.EndPrimaryCmd(copyCmd); imageLayout = VkImageLayout.ShaderReadOnlyOptimal; stagingBuffer.Dispose(); imageView = ImageView.Create(image, ImageViewType, format, VkImageAspectFlags.Color, 0, mipLevels, 0, layers); sampler = new Sampler(VkFilter.Linear, VkSamplerMipmapMode.Linear, samplerAddressMode, mipLevels, Device.Features.samplerAnisotropy == true, borderColor); UpdateDescriptor(); }