private void dispose(bool disposing) { if (disposing && !_isDisposed) { if (ReferenceCount > 0) { throw new InvalidOperationException($"Cannot dispose render target \"{Name ?? "none"}\" still in use (uses = {_refCount})"); } VkView?.Dispose(); VkImage.Dispose(); VkMemory?.Dispose(); } _isDisposed = true; }
public void Dispose() { generator.Dispose(); imageAvailableSemaphore.Dispose(); renderFinishedSemaphore.Dispose(); descriptorPool.Dispose(); uniformBuffer.Dispose(); uniformBufferMemory.Dispose(); indexBuffer.Dispose(); indexBufferMemory.Dispose(); vertexBuffer.Dispose(); vertexBufferMemory.Dispose(); textureSampler.Dispose(); textureImageView.Dispose(); textureImage.Dispose(); textureImageMemory.Dispose(); stagingBuffer.Dispose(); stagingBufferMemory.Dispose(); commandPool.Dispose(); foreach (var fb in swapchainFramebuffers) { fb.Dispose(); } pipeline.Dispose(); pipelineLayout.Dispose(); descriptorSetLayout.Dispose(); renderPass.Dispose(); foreach (var iv in swapchainImageViews) { iv.Dispose(); } swapchain.Dispose(); device.Dispose(); surface.Dispose(); instance.Dispose(); window.Dispose(); GLFW.Terminate(); }
/// <summary> /// Rebuilds the render target to use a new size. /// </summary> /// <param name="width">The new width of the render target.</param> /// <param name="height">The new height of the render target.</param> /// <param name="force">If <c>true</c>, the render target will be rebuilt even if the size doesnt change.</param> public void Rebuild(uint width, uint height, bool force = false) { if (!force && width == Width && height == Height) { return; } Width = width; Height = height; // Destroy the existing objects, if needed VkView?.Dispose(); VkImage?.Dispose(); VkMemory?.Dispose(); // Create the image var ici = new Vk.ImageCreateInfo { ImageType = Vk.ImageType.Image2D, Extent = new Vk.Extent3D((int)width, (int)height, 1), MipLevels = 1, ArrayLayers = 1, Format = (Vk.Format)Format, Tiling = Vk.ImageTiling.Optimal, InitialLayout = Vk.ImageLayout.Undefined, Usage = Vk.ImageUsages.Sampled | Vk.ImageUsages.TransferSrc | Vk.ImageUsages.TransferDst | (HasDepth ? Vk.ImageUsages.DepthStencilAttachment : Vk.ImageUsages.ColorAttachment), // No subpassInput support yet, but add it here SharingMode = Vk.SharingMode.Exclusive, Samples = Vk.SampleCounts.Count1, // TODO: Change when we support multisampling 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 render targets (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)Format, new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1), viewType: Vk.ImageViewType.Image2D ); 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(VkAspects, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.None, Vk.ImageLayout.Undefined, DefaultImageLayout ) }); }); // Build the transitions ClearBarrier = new Vk.ImageMemoryBarrier( VkImage, new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.None, DefaultImageLayout, Vk.ImageLayout.TransferDstOptimal ); AttachBarrier = new Vk.ImageMemoryBarrier( VkImage, new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.None, Vk.ImageLayout.TransferDstOptimal, DefaultImageLayout ); }