public ShadowPass() : base(SubmitQueue.EarlyGraphics) { var depthFormat = Device.GetSupportedDepthFormat(); for (uint i = 0; i < SHADOW_MAP_CASCADE_COUNT; i++) { cascades[i].view = ImageView.Create(DepthRT.image, VkImageViewType.Image2DArray, depthFormat, VkImageAspectFlags.Depth, 0, 1, i, 1); } ubShadow = new SharedBuffer(VkBufferUsageFlags.UniformBuffer, (uint)(SHADOW_MAP_CASCADE_COUNT * Utilities.SizeOf <mat4>())); depthShader = Resources.Instance.Load <Shader>("shaders/shadow.shader"); vsSet = new DescriptorSet(depthShader.Main.GetResourceLayout(0), ubShadow, FrameGraph.TransformBuffer); }
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 static Texture Create(uint width, uint height, VkImageViewType imageViewType, uint layers, VkFormat format, uint levels = 0, VkImageUsageFlags additionalUsage = VkImageUsageFlags.None) { Texture texture = new Texture { extent = new VkExtent3D(width, height, 1), layers = layers, mipLevels = (levels > 0) ? levels : (uint)NumMipmapLevels(width, height), }; VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst | additionalUsage; if (texture.mipLevels > 1) { usage |= VkImageUsageFlags.TransferSrc; // For mipmap generation } texture.image = Image.Create(width, height, (imageViewType == VkImageViewType.ImageCube || imageViewType == VkImageViewType.ImageCubeArray) ? VkImageCreateFlags.CubeCompatible : VkImageCreateFlags.None, layers, texture.mipLevels, format, VkSampleCountFlags.Count1, usage); texture.imageView = ImageView.Create(texture.image, imageViewType, format, VkImageAspectFlags.Color, 0, Vulkan.RemainingMipLevels, 0, layers); texture.sampler = new Sampler(VkFilter.Linear, VkSamplerMipmapMode.Linear, VkSamplerAddressMode.ClampToBorder, texture.mipLevels, Device.Features.samplerAnisotropy == true); texture.UpdateDescriptor(); return(texture); }
// Prepare a texture target that is used to store compute shader calculations public static Texture CreateStorage(uint width, uint height, VkFormat format) { var texture = new Texture { extent = new VkExtent3D(width, height, 1), mipLevels = 1, format = format }; var createInfo = new VkImageCreateInfo { sType = VkStructureType.ImageCreateInfo, flags = VkImageCreateFlags.None, imageType = VkImageType.Image2D, format = format, extent = new VkExtent3D(width, height, 1), mipLevels = 1, arrayLayers = 1, samples = VkSampleCountFlags.Count1, tiling = VkImageTiling.Optimal, usage = VkImageUsageFlags.Storage | VkImageUsageFlags.Sampled, sharingMode = VkSharingMode.Exclusive, initialLayout = VkImageLayout.Preinitialized }; texture.image = new Image(ref createInfo); Graphics.WithCommandBuffer((cmd) => { cmd.SetImageLayout(texture.image, VkImageAspectFlags.Color, VkImageLayout.Preinitialized, VkImageLayout.General); }); texture.imageLayout = VkImageLayout.General; 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); 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(); }
/** * Create the swapchain and get it's Images with given width and height * * @param width Pointer to the width of the swapchain (may be adjusted to fit the requirements of the swapchain) * @param height Pointer to the height of the swapchain (may be adjusted to fit the requirements of the swapchain) * @param vsync (Optional) Can be used to force vsync'd rendering (by using VK_PRESENT_MODE_FIFO_KHR as presentation mode) */ public unsafe void Create(ref uint width, ref uint height, bool vsync = false) { VkResult err; VkSwapchainKHR oldSwapchain = swapchain; // Get physical Device Surface properties and formats VkSurfaceCapabilitiesKHR surfCaps; err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Device.PhysicalDevice, Surface, out surfCaps); Debug.Assert(err == VkResult.Success); // Get available present modes uint presentModeCount; err = vkGetPhysicalDeviceSurfacePresentModesKHR(Device.PhysicalDevice, Surface, &presentModeCount, null); Debug.Assert(err == VkResult.Success); Debug.Assert(presentModeCount > 0); using (Vector <VkPresentModeKHR> presentModes = new Vector <VkPresentModeKHR>(presentModeCount)) { err = vkGetPhysicalDeviceSurfacePresentModesKHR(Device.PhysicalDevice, Surface, &presentModeCount, (VkPresentModeKHR *)presentModes.Data); Debug.Assert(err == VkResult.Success); presentModes.Count = presentModeCount; // If width (and height) equals the special value 0xFFFFFFFF, the size of the Surface will be set by the swapchain if (surfCaps.currentExtent.width != unchecked ((uint)-1)) { width = surfCaps.currentExtent.width; height = surfCaps.currentExtent.height; } extent = new VkExtent3D(width, height, 1); // Select a present mode for the swapchain // The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec // This mode waits for the vertical blank ("v-sync") VkPresentModeKHR swapchainPresentMode = VkPresentModeKHR.Fifo; // If v-sync is not requested, try to find a mailbox mode // It's the lowest latency non-tearing present mode available if (!vsync) { for (uint i = 0; i < presentModeCount; i++) { if (presentModes[i] == VkPresentModeKHR.Mailbox) { swapchainPresentMode = VkPresentModeKHR.Mailbox; break; } if ((swapchainPresentMode != VkPresentModeKHR.Mailbox) && (presentModes[i] == VkPresentModeKHR.Immediate)) { swapchainPresentMode = VkPresentModeKHR.Immediate; } } } // Determine the number of Images uint desiredNumberOfSwapchainImages = IMAGE_COUNT;// surfCaps.minImageCount + 1; if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) { Debug.Assert(false); desiredNumberOfSwapchainImages = surfCaps.maxImageCount; } // Find the transformation of the Surface VkSurfaceTransformFlagsKHR preTransform; if ((surfCaps.supportedTransforms & VkSurfaceTransformFlagsKHR.Identity) != 0) { // We prefer a non-rotated transform preTransform = VkSurfaceTransformFlagsKHR.Identity; } else { preTransform = surfCaps.currentTransform; } VkSwapchainCreateInfoKHR swapchainCI = new VkSwapchainCreateInfoKHR { sType = VkStructureType.SwapchainCreateInfoKHR, pNext = null, surface = Surface, minImageCount = desiredNumberOfSwapchainImages, imageFormat = ColorFormat, imageColorSpace = ColorSpace, imageExtent = new VkExtent2D(extent.width, extent.height), imageUsage = VkImageUsageFlags.ColorAttachment, preTransform = preTransform, imageArrayLayers = 1, imageSharingMode = VkSharingMode.Exclusive, queueFamilyIndexCount = 0, pQueueFamilyIndices = null, presentMode = swapchainPresentMode, oldSwapchain = oldSwapchain, // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the Surface area clipped = true, compositeAlpha = VkCompositeAlphaFlagsKHR.Opaque }; // Set additional usage flag for blitting from the swapchain Images if supported Device.GetPhysicalDeviceFormatProperties(ColorFormat, out VkFormatProperties formatProps); if ((formatProps.optimalTilingFeatures & VkFormatFeatureFlags.BlitDst) != 0) { swapchainCI.imageUsage |= VkImageUsageFlags.TransferSrc; } swapchain = Device.CreateSwapchainKHR(ref swapchainCI); // If an existing swap chain is re-created, destroy the old swap chain // This also cleans up all the presentable Images if (oldSwapchain.Handle != 0) { for (uint i = 0; i < ImageCount; i++) { ImageViews[i].Dispose(); } Device.DestroySwapchainKHR(oldSwapchain); } var vkImages = Vulkan.vkGetSwapchainImagesKHR(Device.Handle, swapchain); VkImages.Clear(); Images = new Image[vkImages.Length]; ImageViews = new ImageView[vkImages.Length]; for (int i = 0; i < vkImages.Length; i++) { Images[i] = new Image(vkImages[i]) { imageType = VkImageType.Image2D, extent = extent }; ImageViews[i] = ImageView.Create(Images[i], VkImageViewType.Image2D, ColorFormat, VkImageAspectFlags.Color, 0, 1); } // Get the swap chain Images VkImages.Add(vkImages); } }