// Sets up the command buffer that renders the scene to the offscreen frame buffer void buildOffscreenCommandBuffer() { if (offscreenPass.commandBuffer == NullHandle) { offscreenPass.commandBuffer = createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, false); } if (offscreenPass.semaphore == NullHandle) { VkSemaphoreCreateInfo semaphoreCreateInfo = Initializers.semaphoreCreateInfo(); Util.CheckResult(vkCreateSemaphore(device, &semaphoreCreateInfo, null, out offscreenPass.semaphore)); } VkCommandBufferBeginInfo cmdBufInfo = Initializers.commandBufferBeginInfo(); FixedArray2 <VkClearValue> clearValues = new FixedArray2 <VkClearValue>(); clearValues.First.color = new VkClearColorValue { float32_0 = 0.0f, float32_1 = 0.0f, float32_2 = 0.0f, float32_3 = 0.0f }; clearValues.Second.depthStencil = new VkClearDepthStencilValue { depth = 1.0f, stencil = 0 }; VkRenderPassBeginInfo renderPassBeginInfo = Initializers.renderPassBeginInfo(); renderPassBeginInfo.renderPass = offscreenPass.renderPass; renderPassBeginInfo.framebuffer = offscreenPass.frameBuffer; renderPassBeginInfo.renderArea.extent.width = offscreenPass.width; renderPassBeginInfo.renderArea.extent.height = offscreenPass.height; renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = &clearValues.First; Util.CheckResult(vkBeginCommandBuffer(offscreenPass.commandBuffer, &cmdBufInfo)); VkViewport viewport = Initializers.viewport((float)offscreenPass.width, (float)offscreenPass.height, 0.0f, 1.0f); vkCmdSetViewport(offscreenPass.commandBuffer, 0, 1, &viewport); VkRect2D scissor = Initializers.rect2D(offscreenPass.width, offscreenPass.height, 0, 0); vkCmdSetScissor(offscreenPass.commandBuffer, 0, 1, &scissor); vkCmdBeginRenderPass(offscreenPass.commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindDescriptorSets(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts_scene, 0, 1, ref descriptorSets_scene, 0, null); vkCmdBindPipeline(offscreenPass.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines_colorPass); ulong offsets = 0; vkCmdBindVertexBuffers(offscreenPass.commandBuffer, VERTEX_BUFFER_BIND_ID, 1, ref models_example.vertices.buffer, &offsets); vkCmdBindIndexBuffer(offscreenPass.commandBuffer, models_example.indices.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdDrawIndexed(offscreenPass.commandBuffer, models_example.indexCount, 1, 0, 0, 0); vkCmdEndRenderPass(offscreenPass.commandBuffer); Util.CheckResult(vkEndCommandBuffer(offscreenPass.commandBuffer)); }
public void InitVulkan() { VkResult err; err = CreateInstance(false); if (err != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan instance. Error: " + err); } if (Settings.Validation) { } // 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 // Select physical Device to be used for the Vulkan example // Defaults to the first Device unless specified by command line uint selectedDevice = 0; // TODO: Implement arg parsing, etc. physicalDevice = ((VkPhysicalDevice *)physicalDevices)[selectedDevice]; // 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; Swapchain.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; }