Beispiel #1
0
        public unsafe Image(ref VkImageCreateInfo imageCreateInfo)
        {
            handle      = Device.CreateImage(ref imageCreateInfo);
            imageType   = imageCreateInfo.imageType;
            format      = imageCreateInfo.format;
            extent      = imageCreateInfo.extent;
            mipLevels   = imageCreateInfo.mipLevels;
            arrayLayers = imageCreateInfo.arrayLayers;

            Device.GetImageMemoryRequirements(this, out var memReqs);

            Allocate(memReqs);

            Device.BindImageMemory(handle, memory, 0);
        }
Beispiel #2
0
        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();
        }
Beispiel #3
0
        /**
         * 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);
            }
        }