Example #1
0
        private protected Texture(TextureType type, uint w, uint h, uint d, uint layers)
        {
            Device = SpectrumApp.Instance.GraphicsDevice;

            Type   = type;
            Width  = w;
            Height = h;
            Depth  = d;
            Layers = layers;

            // Limits checking
            if (w == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(w), "A texture cannot have a width of zero");
            }
            if (h == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(h), "A texture cannot have a height of zero");
            }
            if (d == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(d), "A texture cannot have a depth of zero");
            }
            if (layers == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(layers), "A texture cannot have 0 layers");
            }
            if (type == TextureType.Texture3D && layers != 1)
            {
                throw new ArgumentOutOfRangeException(nameof(layers), "3D textures cannot be arrays");
            }
            if (layers > Limits.MaxTextureLayers)
            {
                throw new ArgumentOutOfRangeException(nameof(layers), $"The texture array count ({layers}) is too big for the device ({Limits.MaxTextureLayers})");
            }
            switch (type)
            {
            case TextureType.Texture1D:
                if (w > Limits.MaxTextureSize1D)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(w), $"The 1D texture size ({w}) is too big for the device ({Limits.MaxTextureSize1D})"
                              );
                }
                break;

            case TextureType.Texture2D:
                if (w > Limits.MaxTextureSize2D || h > Limits.MaxTextureSize2D)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(w), $"The 2D texture size ({w}x{h}) is too big for the device ({Limits.MaxTextureSize2D})"
                              );
                }
                break;

            case TextureType.Texture3D:
                if (w > Limits.MaxTextureSize3D || h > Limits.MaxTextureSize3D || d > Limits.MaxTextureSize3D)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(w), $"The 3D texture size ({w}x{h}x{d}) is too big for the device ({Limits.MaxTextureSize3D})"
                              );
                }
                break;
            }

            // Create the image
            var ici = new Vk.ImageCreateInfo {
                ImageType     = (Vk.ImageType)type,
                Extent        = new Vk.Extent3D((int)w, (int)h, (int)d),
                MipLevels     = 1,
                ArrayLayers   = (int)layers,
                Format        = Vk.Format.R8G8B8A8UNorm,
                Tiling        = Vk.ImageTiling.Optimal,
                InitialLayout = Vk.ImageLayout.Undefined,
                Usage         = Vk.ImageUsages.TransferDst | Vk.ImageUsages.Sampled | Vk.ImageUsages.TransferSrc,
                SharingMode   = Vk.SharingMode.Exclusive,
                Samples       = Vk.SampleCounts.Count1,
                Flags         = Vk.ImageCreateFlags.None
            };

            VkImage = Device.VkDevice.CreateImage(ici);

            // Create the backing memory for the image
            var memReq = VkImage.GetMemoryRequirements();
            var memIdx = Device.FindMemoryTypeIndex(memReq.MemoryTypeBits, Vk.MemoryProperties.DeviceLocal);

            if (memIdx == -1)
            {
                throw new InvalidOperationException("Cannot find a memory type that supports textures (this means bad or out-of-date hardware)");
            }
            var mai = new Vk.MemoryAllocateInfo(memReq.Size, memIdx);

            VkMemory = Device.VkDevice.AllocateMemory(mai);
            DataSize = (uint)memReq.Size;
            VkImage.BindMemory(VkMemory);

            // Create the view
            var vci = new Vk.ImageViewCreateInfo(
                Vk.Format.R8G8B8A8UNorm,
                new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, (int)Layers),
                viewType: GetViewType(Type, layers)
                );

            VkView = VkImage.CreateView(vci);

            // Make the initial layout transition
            Device.SubmitScratchCommand(buf => {
                buf.CmdPipelineBarrier(Vk.PipelineStages.AllGraphics, Vk.PipelineStages.AllGraphics, imageMemoryBarriers: new[] { new Vk.ImageMemoryBarrier(
                                                                                                                                      VkImage, new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.ShaderRead,
                                                                                                                                      Vk.ImageLayout.Undefined, Vk.ImageLayout.ShaderReadOnlyOptimal
                                                                                                                                      ) });
            });
        }