public FrameBuffer(GraphicsDevice device, RenderPass renderPass, DepthStencil depthStencil, Swapchain swapchain, uint swapchainImageIndex) { this.device = device; this.renderPass = renderPass; this.depthStencil = depthStencil; this.swapchain = swapchain; this.swapchainImageIndex = swapchainImageIndex; Setup(); }
public static RenderPass Single(GraphicsDevice device, Swapchain swapchain = null) { if (swapchain == null) { swapchain = device.mainSwapchain; } RenderPass newPass = new RenderPass(device); newPass.SetupSinglePass(swapchain); return(newPass); }
public static RenderPass ClearTargetsPass(GraphicsDevice device, Swapchain swapchain = null) { if (swapchain == null) { swapchain = device.mainSwapchain; } RenderPass newPass = new RenderPass(device); newPass.SetupClearAttachmentsPass(swapchain); return(newPass); }
public CommandPool(GraphicsDevice device, Swapchain swapchain) { this.device = device; VkCommandPoolCreateInfo cmdPoolInfo = VkCommandPoolCreateInfo.New(); cmdPoolInfo.queueFamilyIndex = swapchain.vkSwapchain.QueueNodeIndex; cmdPoolInfo.flags = VkCommandPoolCreateFlags.ResetCommandBuffer | VkCommandPoolCreateFlags.Transient; Util.CheckResult(vkCreateCommandPool(device.device, &cmdPoolInfo, null, out vkCmdPool)); AllocateBuffers(VkCommandBufferLevel.Primary, 2); AllocateBuffers(VkCommandBufferLevel.Secondary, 2); }
/// <summary> /// Must be called outside of a renderpass scope. /// </summary> /// <param name="depthStencil"></param> /// <param name="clearValue"></param> public void ClearColor(Swapchain swapchain, uint swapchainImageIndex, VkClearColorValue clearColor) { CheckBegun(); CheckNotInRenderPass(); VkClearValue clearValue = new VkClearValue(); clearValue.color = clearColor; VkImageSubresourceRange imageRange = new VkImageSubresourceRange(); imageRange.aspectMask = VkImageAspectFlags.Color; imageRange.levelCount = 1; imageRange.layerCount = 1; vkCmdClearColorImage(vkCmd, swapchain.vkSwapchain.Images[swapchainImageIndex], VkImageLayout.General, &clearColor, 1, &imageRange); }
public GraphicsDevice(bool enableValidation) { VkResult err; err = CreateInstance("VulkanDevice", enableValidation); if (err != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan instance. Error: " + err); } // Physical Device uint gpuCount = 0; Util.CheckResult(vkEnumeratePhysicalDevices(Instance, &gpuCount, null)); Debug.Assert(gpuCount > 0); // Enumerate devices IntPtr *physicalDevices = stackalloc IntPtr[(int)gpuCount]; err = vkEnumeratePhysicalDevices(Instance, &gpuCount, (VkPhysicalDevice *)physicalDevices); if (err != VkResult.Success) { throw new InvalidOperationException("Could not enumerate physical devices."); } // GPU selection uint selectedDevice = 0; VkPhysicalDeviceType bestType = VkPhysicalDeviceType.Other; ulong bestDeviceLocalMemSize = 0; for (uint i = 0; i < gpuCount; i++) { VkPhysicalDevice device = ((VkPhysicalDevice *)physicalDevices)[i]; VkPhysicalDeviceProperties devProps; vkGetPhysicalDeviceProperties(device, &devProps); if (devProps.deviceType == VkPhysicalDeviceType.IntegratedGpu && bestType != VkPhysicalDeviceType.IntegratedGpu && bestType != VkPhysicalDeviceType.DiscreteGpu) { selectedDevice = i; bestType = VkPhysicalDeviceType.IntegratedGpu; bestDeviceLocalMemSize = GetDeviceLocalMemorySize(device); } else if (devProps.deviceType == VkPhysicalDeviceType.DiscreteGpu && bestType != VkPhysicalDeviceType.DiscreteGpu) { //Found a discrete GPU, we can choose it. selectedDevice = i; bestType = VkPhysicalDeviceType.DiscreteGpu; bestDeviceLocalMemSize = GetDeviceLocalMemorySize(device); } else if (devProps.deviceType == VkPhysicalDeviceType.DiscreteGpu && bestType == VkPhysicalDeviceType.DiscreteGpu) { ulong memSize = GetDeviceLocalMemorySize(device); if (memSize > bestDeviceLocalMemSize) { } selectedDevice = i; bestType = VkPhysicalDeviceType.DiscreteGpu; bestDeviceLocalMemSize = memSize; } } Console.WriteLine($"Found a vulkan capable GPU of type {bestType} at location {selectedDevice}. With {bestDeviceLocalMemSize / (1024 * 1024)}MiB of memory."); // Select physical Device to be used for the Vulkan example // Defaults to the first Device unless specified by command line // TODO: Implement arg parsing, etc. physicalDevice = ((VkPhysicalDevice *)physicalDevices)[selectedDevice]; Console.WriteLine(PrintDeviceMemoryData(physicalDevice)); // Store properties (including limits) and features of the phyiscal Device // So examples can check against them and see if a feature is actually supported VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); DeviceProperties = deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); DeviceFeatures = deviceFeatures; // Gather physical Device memory properties VkPhysicalDeviceMemoryProperties deviceMemoryProperties; vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); DeviceMemoryProperties = deviceMemoryProperties; // Derived examples can override this to set actual features (based on above readings) to enable for logical device creation //getEnabledFeatures(); // Vulkan Device creation // This is handled by a separate class that gets a logical Device representation // and encapsulates functions related to a Device vulkanDevice = new vksVulkanDevice(physicalDevice); VkResult res = vulkanDevice.CreateLogicalDevice(enabledFeatures, EnabledExtensions); if (res != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan Device."); } device = vulkanDevice.LogicalDevice; // Get a graphics queue from the Device VkQueue queue; vkGetDeviceQueue(device, vulkanDevice.QFIndices.Graphics, 0, &queue); this.queue = queue; // Find a suitable depth format VkFormat depthFormat; uint validDepthFormat = Tools.GetSupportedDepthFormat(physicalDevice, &depthFormat); Debug.Assert(validDepthFormat == True); DepthFormat = depthFormat; mainSwapchain = new Swapchain(this); mainSwapchain.Connect(Instance, physicalDevice, device); // Create synchronization objects VkSemaphoreCreateInfo semaphoreCreateInfo = Initializers.semaphoreCreateInfo(); // Create a semaphore used to synchronize image presentation // Ensures that the image is displayed before we start submitting new commands to the queu Util.CheckResult(vkCreateSemaphore(device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->PresentComplete)); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands have been sumbitted and executed Util.CheckResult(vkCreateSemaphore(device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->RenderComplete)); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands for the text overlay have been sumbitted and executed // Will be inserted after the render complete semaphore if the text overlay is enabled Util.CheckResult(vkCreateSemaphore(device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->TextOverlayComplete)); // Set up submit info structure // Semaphores will stay the same during application lifetime // Command buffer submission info is set by each example submitInfo = Initializers.SubmitInfo(); submitInfo.pWaitDstStageMask = (VkPipelineStageFlags *)submitPipelineStages.Data; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &GetSemaphoresPtr()->PresentComplete; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &GetSemaphoresPtr()->RenderComplete; memoryAllocator = new VulkanMemoryAllocator(this); }
public DepthStencil(GraphicsDevice device, Swapchain swapchain) { this.device = device; this.swapchain = swapchain; Setup(); }
private void SetupClearAttachmentsPass(Swapchain swapchain) { using (NativeList <VkAttachmentDescription> attachments = new NativeList <VkAttachmentDescription>()) { attachments.Count = 2; // Color attachment attachments[0] = new VkAttachmentDescription(); attachments[0].format = swapchain.vkSwapchain.ColorFormat; attachments[0].samples = VkSampleCountFlags.Count1; attachments[0].loadOp = VkAttachmentLoadOp.Clear; attachments[0].storeOp = VkAttachmentStoreOp.Store; attachments[0].stencilLoadOp = VkAttachmentLoadOp.DontCare; attachments[0].stencilStoreOp = VkAttachmentStoreOp.DontCare; attachments[0].initialLayout = VkImageLayout.Undefined; attachments[0].finalLayout = VkImageLayout.ColorAttachmentOptimal; //TODO // Depth attachment attachments[1] = new VkAttachmentDescription(); attachments[1].format = device.DepthFormat; attachments[1].samples = VkSampleCountFlags.Count1; attachments[1].loadOp = VkAttachmentLoadOp.Clear; attachments[1].storeOp = VkAttachmentStoreOp.Store; attachments[1].stencilLoadOp = VkAttachmentLoadOp.DontCare; attachments[1].stencilStoreOp = VkAttachmentStoreOp.DontCare; attachments[1].initialLayout = VkImageLayout.Undefined; attachments[1].finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; VkAttachmentReference colorReference = new VkAttachmentReference(); colorReference.attachment = 0; colorReference.layout = VkImageLayout.ColorAttachmentOptimal; VkAttachmentReference depthReference = new VkAttachmentReference(); depthReference.attachment = 1; depthReference.layout = VkImageLayout.DepthStencilAttachmentOptimal; VkSubpassDescription subpassDescription = new VkSubpassDescription(); subpassDescription.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpassDescription.colorAttachmentCount = 1; subpassDescription.pColorAttachments = &colorReference; subpassDescription.pDepthStencilAttachment = &depthReference; subpassDescription.inputAttachmentCount = 0; subpassDescription.pInputAttachments = null; subpassDescription.preserveAttachmentCount = 0; subpassDescription.pPreserveAttachments = null; subpassDescription.pResolveAttachments = null; // Subpass dependencies for layout transitions using (NativeList <VkSubpassDependency> dependencies = new NativeList <VkSubpassDependency>(2)) { dependencies.Count = 2; dependencies[0].srcSubpass = SubpassExternal; dependencies[0].dstSubpass = 0; dependencies[0].srcStageMask = VkPipelineStageFlags.BottomOfPipe; dependencies[0].dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[0].srcAccessMask = VkAccessFlags.MemoryRead; dependencies[0].dstAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); dependencies[0].dependencyFlags = VkDependencyFlags.ByRegion; dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = SubpassExternal; dependencies[1].srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[1].dstStageMask = VkPipelineStageFlags.BottomOfPipe; dependencies[1].srcAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); dependencies[1].dstAccessMask = VkAccessFlags.MemoryRead; dependencies[1].dependencyFlags = VkDependencyFlags.ByRegion; VkRenderPassCreateInfo renderPassInfo = new VkRenderPassCreateInfo(); renderPassInfo.sType = VkStructureType.RenderPassCreateInfo; renderPassInfo.attachmentCount = attachments.Count; renderPassInfo.pAttachments = (VkAttachmentDescription *)attachments.Data.ToPointer(); renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpassDescription; renderPassInfo.dependencyCount = dependencies.Count; renderPassInfo.pDependencies = (VkSubpassDependency *)dependencies.Data; Util.CheckResult(vkCreateRenderPass(device.device, &renderPassInfo, null, out vkRenderPass)); } } }