public MgTextureInfo Load(byte[] imageData, MgImageSource source, IMgAllocationCallbacks allocator, IMgFence fence) { // Prefer using optimal tiling, as linear tiling // may support only a small set of features // depending on implementation (e.g. no mip maps, only one layer, etc.) IMgImage mappableImage; IMgDeviceMemory mappableMemory; uint mipLevels = (uint)source.Mipmaps.Length; // Load mip map level 0 to linear tiling image var imageCreateInfo = new MgImageCreateInfo { ImageType = MgImageType.TYPE_2D, Format = source.Format, MipLevels = mipLevels, ArrayLayers = 1, Samples = MgSampleCountFlagBits.COUNT_1_BIT, Tiling = MgImageTiling.LINEAR, Usage = MgImageUsageFlagBits.SAMPLED_BIT, SharingMode = MgSharingMode.EXCLUSIVE, InitialLayout = MgImageLayout.PREINITIALIZED, Extent = new MgExtent3D { Width = source.Width, Height = source.Height, Depth = 1 }, }; var device = mGraphicsConfiguration.Device; var err = device.CreateImage(imageCreateInfo, allocator, out mappableImage); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Get memory requirements for this image // like size and alignment MgMemoryRequirements memReqs; device.GetImageMemoryRequirements(mappableImage, out memReqs); // Set memory allocation size to required memory size var memAllocInfo = new MgMemoryAllocateInfo { AllocationSize = memReqs.Size, }; Debug.Assert(mGraphicsConfiguration.Partition != null); // Get memory type that can be mapped to host memory uint memoryTypeIndex; bool isValid = mGraphicsConfiguration.Partition.GetMemoryType(memReqs.MemoryTypeBits, MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT, out memoryTypeIndex); Debug.Assert(isValid); memAllocInfo.MemoryTypeIndex = memoryTypeIndex; // Allocate host memory err = device.AllocateMemory(memAllocInfo, allocator, out mappableMemory); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Bind allocated image for use err = mappableImage.BindImageMemory(device, mappableMemory, 0); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Get sub resource layout // Mip map count, array layer, etc. var subRes = new MgImageSubresource { AspectMask = MgImageAspectFlagBits.COLOR_BIT, }; MgSubresourceLayout subResLayout; IntPtr data; // Get sub resources layout // Includes row pitch, size offsets, etc. device.GetImageSubresourceLayout(mappableImage, subRes, out subResLayout); // Map image memory err = mappableMemory.MapMemory(device, 0, memReqs.Size, 0, out data); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Copy image data into memory //memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); Marshal.Copy(imageData, 0, data, (int)source.Size); mappableMemory.UnmapMemory(device); // Linear tiled images don't need to be staged // and can be directly used as textures var texture = new MgTextureInfo { Image = mappableImage, DeviceMemory = mappableMemory, ImageLayout = MgImageLayout.SHADER_READ_ONLY_OPTIMAL, }; var cmdPool = mGraphicsConfiguration.Partition.CommandPool; var cmdBufAllocateInfo = new MgCommandBufferAllocateInfo { CommandPool = cmdPool, Level = MgCommandBufferLevel.PRIMARY, CommandBufferCount = 1, }; var commands = new IMgCommandBuffer[1]; err = device.AllocateCommandBuffers(cmdBufAllocateInfo, commands); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); var cmdBufInfo = new MgCommandBufferBeginInfo { Flags = 0, }; texture.Command = commands [0]; err = commands[0].BeginCommandBuffer(cmdBufInfo); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Setup image memory barrier transfer image to shader read layout mImageTools.SetImageLayout( texture.Command, texture.Image, MgImageAspectFlagBits.COLOR_BIT, MgImageLayout.PREINITIALIZED, texture.ImageLayout, 0, mipLevels); err = texture.Command.EndCommandBuffer(); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); var submitInfo = new MgSubmitInfo { CommandBuffers = commands, }; var queue = mGraphicsConfiguration.Queue; queue.QueueSubmit(new[] { submitInfo }, fence); // // NOT SURE IF // err = queue.QueueWaitIdle(); // Debug.Assert (err == Result.SUCCESS, err + " != Result.SUCCESS"); // // device.FreeCommandBuffers(cmdPool, commands); // texture.Command = copyCmd; return(texture); }
// FROM texture.cpp (2016) Sascha Williams public MgTextureInfo Load(byte[] imageData, MgImageSource source, IMgAllocationCallbacks allocator, IMgFence fence) { var device = mGraphicsConfiguration.Device; var queue = mGraphicsConfiguration.Queue; var cmdPool = mGraphicsConfiguration.Partition.CommandPool; uint mipLevels = (uint)source.Mipmaps.Length; // Create a host-visible staging buffer that contains the raw image data IMgBuffer stagingBuffer; IMgDeviceMemory stagingMemory; var bufferCreateInfo = new MgBufferCreateInfo { Size = source.Size, Usage = MgBufferUsageFlagBits.TRANSFER_SRC_BIT, SharingMode = MgSharingMode.EXCLUSIVE, }; // This buffer is used as a transfer source for the buffer copy var result = device.CreateBuffer(bufferCreateInfo, allocator, out stagingBuffer); Debug.Assert(result == Result.SUCCESS); MgMemoryRequirements memReqs; // Get memory requirements for the staging buffer (alignment, memory type bits) mGraphicsConfiguration.Device.GetBufferMemoryRequirements(stagingBuffer, out memReqs); var memAllocInfo = new MgMemoryAllocateInfo { AllocationSize = memReqs.Size, }; // Get memory type index for a host visible buffer uint memoryTypeIndex; bool isTypeValid = mGraphicsConfiguration.Partition.GetMemoryType(memReqs.MemoryTypeBits, MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT, out memoryTypeIndex); Debug.Assert(isTypeValid); memAllocInfo.MemoryTypeIndex = memoryTypeIndex; result = device.AllocateMemory(memAllocInfo, allocator, out stagingMemory); Debug.Assert(result == Result.SUCCESS); result = stagingBuffer.BindBufferMemory(device, stagingMemory, 0); Debug.Assert(result == Result.SUCCESS); // Copy texture data into staging buffer IntPtr data; result = stagingMemory.MapMemory(device, 0, memReqs.Size, 0, out data); Debug.Assert(result == Result.SUCCESS); // TODO : Copy here Marshal.Copy(imageData, 0, data, (int)source.Size); stagingMemory.UnmapMemory(device); // Setup buffer copy regions for each mip level var bufferCopyRegions = new MgBufferImageCopy[source.Mipmaps.Length]; for (uint i = 0; i < bufferCopyRegions.Length; ++i) { bufferCopyRegions [i] = new MgBufferImageCopy { ImageSubresource = new MgImageSubresourceLayers { AspectMask = MgImageAspectFlagBits.COLOR_BIT, MipLevel = i, BaseArrayLayer = 0, LayerCount = 1, }, ImageExtent = new MgExtent3D { Width = source.Mipmaps[i].Width, Height = source.Mipmaps[i].Height, Depth = 1, }, BufferOffset = source.Mipmaps[i].Offset, }; } // Create optimal tiled target image var imageCreateInfo = new MgImageCreateInfo { ImageType = MgImageType.TYPE_2D, Format = source.Format, MipLevels = mipLevels, ArrayLayers = 1, Samples = MgSampleCountFlagBits.COUNT_1_BIT, Tiling = MgImageTiling.OPTIMAL, SharingMode = MgSharingMode.EXCLUSIVE, InitialLayout = MgImageLayout.PREINITIALIZED, Extent = new MgExtent3D { Width = source.Width, Height = source.Height, Depth = 1 }, Usage = MgImageUsageFlagBits.TRANSFER_DST_BIT | MgImageUsageFlagBits.SAMPLED_BIT, }; var texture = new MgTextureInfo(); IMgImage image; result = device.CreateImage(imageCreateInfo, allocator, out image); Debug.Assert(result == Result.SUCCESS); texture.Image = image; device.GetImageMemoryRequirements(texture.Image, out memReqs); memAllocInfo.AllocationSize = memReqs.Size; isTypeValid = mGraphicsConfiguration.Partition.GetMemoryType(memReqs.MemoryTypeBits, MgMemoryPropertyFlagBits.DEVICE_LOCAL_BIT, out memoryTypeIndex); Debug.Assert(isTypeValid); memAllocInfo.MemoryTypeIndex = memoryTypeIndex; IMgDeviceMemory deviceMem; result = device.AllocateMemory(memAllocInfo, allocator, out deviceMem); Debug.Assert(result == Result.SUCCESS); texture.DeviceMemory = deviceMem; result = texture.Image.BindImageMemory(device, texture.DeviceMemory, 0); Debug.Assert(result == Result.SUCCESS); var cmdBufAllocateInfo = new MgCommandBufferAllocateInfo { CommandPool = cmdPool, Level = MgCommandBufferLevel.PRIMARY, CommandBufferCount = 1, }; var commands = new IMgCommandBuffer[1]; result = device.AllocateCommandBuffers(cmdBufAllocateInfo, commands); Debug.Assert(result == Result.SUCCESS); var cmdBufInfo = new MgCommandBufferBeginInfo { Flags = 0, }; texture.Command = commands [0]; result = commands[0].BeginCommandBuffer(cmdBufInfo); Debug.Assert(result == Result.SUCCESS); // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy mImageTools.SetImageLayout( texture.Command, texture.Image, MgImageAspectFlagBits.COLOR_BIT, MgImageLayout.PREINITIALIZED, MgImageLayout.TRANSFER_DST_OPTIMAL, 0, mipLevels); // Copy mip levels from staging buffer texture.Command.CmdCopyBufferToImage( stagingBuffer, texture.Image, MgImageLayout.TRANSFER_DST_OPTIMAL, bufferCopyRegions ); // Change texture image layout to shader read after all mip levels have been copied texture.ImageLayout = MgImageLayout.SHADER_READ_ONLY_OPTIMAL; mImageTools.SetImageLayout( texture.Command, texture.Image, MgImageAspectFlagBits.COLOR_BIT, MgImageLayout.TRANSFER_DST_OPTIMAL, texture.ImageLayout, 0, mipLevels); result = texture.Command.EndCommandBuffer(); Debug.Assert(result == Result.SUCCESS); var submitInfo = new MgSubmitInfo { CommandBuffers = commands, }; queue.QueueSubmit(new[] { submitInfo }, fence); // result = queue.QueueWaitIdle(); // Debug.Assert (result == Result.SUCCESS); // // device.FreeCommandBuffers(cmdPool, commands); // texture.Command = copyCmd; // Clean up staging resources stagingMemory.FreeMemory(device, allocator); stagingBuffer.DestroyBuffer(device, allocator); return(texture); }
void CreateDepthStencil(IMgCommandBuffer setupCmdBuffer, MgGraphicsDeviceCreateInfo createInfo) { var image = new MgImageCreateInfo { ImageType = MgImageType.TYPE_2D, Format = createInfo.DepthStencil, Extent = new MgExtent3D { Width = createInfo.Width, Height = createInfo.Height, Depth = 1 }, MipLevels = 1, ArrayLayers = 1, Samples = createInfo.Samples, Tiling = MgImageTiling.OPTIMAL, // TODO : multisampled uses MgImageUsageFlagBits.TRANSIENT_ATTACHMENT_BIT | MgImageUsageFlagBits.DEPTH_STENCIL_ATTACHMENT_BIT; Usage = MgImageUsageFlagBits.DEPTH_STENCIL_ATTACHMENT_BIT | MgImageUsageFlagBits.TRANSFER_SRC_BIT, Flags = 0, }; var mem_alloc = new MgMemoryAllocateInfo { AllocationSize = 0, MemoryTypeIndex = 0, }; MgMemoryRequirements memReqs; Debug.Assert(mGraphicsConfiguration.Partition != null); Result err; { IMgImage dsImage; err = mGraphicsConfiguration.Partition.Device.CreateImage(image, null, out dsImage); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); mImage = dsImage; } mGraphicsConfiguration.Partition.Device.GetImageMemoryRequirements(mImage, out memReqs); mem_alloc.AllocationSize = memReqs.Size; uint memTypeIndex; bool memoryTypeFound = mGraphicsConfiguration.Partition.GetMemoryType(memReqs.MemoryTypeBits, MgMemoryPropertyFlagBits.DEVICE_LOCAL_BIT, out memTypeIndex); Debug.Assert(memoryTypeFound); mem_alloc.MemoryTypeIndex = memTypeIndex; { IMgDeviceMemory dsDeviceMemory; err = mGraphicsConfiguration.Partition.Device.AllocateMemory(mem_alloc, null, out dsDeviceMemory); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); mDeviceMemory = dsDeviceMemory; } err = mImage.BindImageMemory(mGraphicsConfiguration.Partition.Device, mDeviceMemory, 0); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); mImageTools.SetImageLayout(setupCmdBuffer, mImage, MgImageAspectFlagBits.DEPTH_BIT | MgImageAspectFlagBits.STENCIL_BIT, MgImageLayout.UNDEFINED, MgImageLayout.DEPTH_STENCIL_ATTACHMENT_OPTIMAL); var depthStencilView = new MgImageViewCreateInfo { Image = mImage, ViewType = MgImageViewType.TYPE_2D, Format = createInfo.DepthStencil, Flags = 0, SubresourceRange = new MgImageSubresourceRange { AspectMask = MgImageAspectFlagBits.DEPTH_BIT | MgImageAspectFlagBits.STENCIL_BIT, BaseMipLevel = 0, LevelCount = 1, BaseArrayLayer = 0, LayerCount = 1, }, }; { IMgImageView dsView; err = mGraphicsConfiguration.Partition.Device.CreateImageView(depthStencilView, null, out dsView); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); mDepthStencilImageView = dsView; } }
public void Create(IMgCommandBuffer cmd, UInt32 width, UInt32 height) { mWidth = width; mHeight = height; Result err; IMgSwapchainKHR oldSwapchain = mSwapChain; Setup(); // Get physical device surface properties and formats MgSurfaceCapabilitiesKHR surfCaps; err = mPartition.PhysicalDevice.GetPhysicalDeviceSurfaceCapabilitiesKHR(mLayer.Surface, out surfCaps); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Get available present modes MgPresentModeKHR[] presentModes; err = mPartition.PhysicalDevice.GetPhysicalDeviceSurfacePresentModesKHR(mLayer.Surface, out presentModes); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); var swapchainExtent = new MgExtent2D { }; // width and height are either both -1, or both not -1. if ((int)surfCaps.CurrentExtent.Width == -1) { // If the surface size is undefined, the size is set to // the size of the images requested. swapchainExtent.Width = mWidth; swapchainExtent.Height = mHeight; } else { // If the surface size is defined, the swap chain size must match swapchainExtent = surfCaps.CurrentExtent; mWidth = surfCaps.CurrentExtent.Width; mHeight = surfCaps.CurrentExtent.Height; } // Prefer mailbox mode if present, it's the lowest latency non-tearing present mode MgPresentModeKHR swapchainPresentMode = MgPresentModeKHR.FIFO_KHR; for (uint i = 0; i < presentModes.Length; i++) { if (presentModes[i] == MgPresentModeKHR.MAILBOX_KHR) { swapchainPresentMode = MgPresentModeKHR.MAILBOX_KHR; break; } if ((swapchainPresentMode != MgPresentModeKHR.MAILBOX_KHR) && (presentModes[i] == MgPresentModeKHR.IMMEDIATE_KHR)) { swapchainPresentMode = MgPresentModeKHR.IMMEDIATE_KHR; } } // Determine the number of images uint desiredNumberOfSwapchainImages = surfCaps.MinImageCount + 1; if ((surfCaps.MaxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.MaxImageCount)) { desiredNumberOfSwapchainImages = surfCaps.MaxImageCount; } MgSurfaceTransformFlagBitsKHR preTransform; if ((surfCaps.SupportedTransforms & MgSurfaceTransformFlagBitsKHR.IDENTITY_BIT_KHR) != 0) { preTransform = MgSurfaceTransformFlagBitsKHR.IDENTITY_BIT_KHR; } else { preTransform = surfCaps.CurrentTransform; } var swapchainCI = new MgSwapchainCreateInfoKHR { Surface = mLayer.Surface, MinImageCount = desiredNumberOfSwapchainImages, ImageFormat = Format, ImageColorSpace = mColorSpace, ImageExtent = swapchainExtent, ImageUsage = MgImageUsageFlagBits.COLOR_ATTACHMENT_BIT, PreTransform = (MgSurfaceTransformFlagBitsKHR)preTransform, ImageArrayLayers = 1, ImageSharingMode = MgSharingMode.EXCLUSIVE, QueueFamilyIndices = null, PresentMode = swapchainPresentMode, OldSwapchain = oldSwapchain, Clipped = true, CompositeAlpha = MgCompositeAlphaFlagBitsKHR.OPAQUE_BIT_KHR, }; err = mPartition.Device.CreateSwapchainKHR(swapchainCI, null, out mSwapChain); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // If an existing swap chain is re-created, destroy the old swap chain // This also cleans up all the presentable images if (oldSwapchain != null) { for (uint i = 0; i < mImageCount; i++) { mBuffers[i].View.DestroyImageView(mPartition.Device, null); } oldSwapchain.DestroySwapchainKHR(mPartition.Device, null); } // Get the swap chain images err = mPartition.Device.GetSwapchainImagesKHR(mSwapChain, out mImages); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); // Get the swap chain buffers containing the image and imageview mImageCount = (uint)mImages.Length; mBuffers = new MgSwapchainBuffer[mImageCount]; for (uint i = 0; i < mImageCount; i++) { var buffer = new MgSwapchainBuffer(); var colorAttachmentView = new MgImageViewCreateInfo { Format = Format, Components = new MgComponentMapping { R = MgComponentSwizzle.R, G = MgComponentSwizzle.G, B = MgComponentSwizzle.B, A = MgComponentSwizzle.A, }, SubresourceRange = new MgImageSubresourceRange { AspectMask = MgImageAspectFlagBits.COLOR_BIT, BaseMipLevel = 0, LevelCount = 1, BaseArrayLayer = 0, LayerCount = 1, }, ViewType = MgImageViewType.TYPE_2D, Flags = 0, }; buffer.Image = mImages[i]; // Transform images from initial (undefined) to present layout mImageTools.SetImageLayout( cmd, buffer.Image, MgImageAspectFlagBits.COLOR_BIT, MgImageLayout.UNDEFINED, MgImageLayout.PRESENT_SRC_KHR); colorAttachmentView.Image = buffer.Image; IMgImageView bufferView; err = mPartition.Device.CreateImageView(colorAttachmentView, null, out bufferView); Debug.Assert(err == Result.SUCCESS, err + " != Result.SUCCESS"); buffer.View = bufferView; mBuffers [i] = buffer; } }