To render a triangle in Vulkan using C#, you can follow these steps:
main.cs// Create a new Vulkan instance. VkInstance instance = new VkInstance();
73 chars3 lines
main.cs// Get the physical device. VkPhysicalDevice[] physical_devices = instance.EnumeratePhysicalDevices(); VkPhysicalDevice physical_device = physical_devices[0]; // Get the device properties. VkPhysicalDeviceProperties device_properties = physical_device.GetProperties();
270 chars7 lines
main.cs// Create the device interface. VkDevice device = physical_device.CreateDevice(); // Get the device queue. VkQueue queue = device.GetQueue(0, 0); // Select a graphics queue family. int queue_family_index = 0; VkDeviceQueueCreateInfo queue_create_info = new VkDeviceQueueCreateInfo { sType = VkStructureType.StructureTypeDeviceQueueCreateInfo, queueFamilyIndex = queue_family_index, queueCount = 1, pQueuePriorities = new float[] { 1.0f }, }; // Create the logical device. VkDevice device = physical_device.CreateDevice(queue_create_infos);
560 chars20 lines
main.cs// Create a swap chain. VkSwapchainKHR swap_chain = device.CreateSwapchainKHR(); // Get the swap chain images. VkImage[] swap_chain_images = device.GetSwapchainImagesKHR(swap_chain); // Get the swap chain image format. VkFormat swap_chain_image_format = device.GetSwapchainImageFormatKHR(swap_chain); // Get the swap chain extent. VkExtent2D swap_chain_extent = device.GetSwapchainExtentKHR(swap_chain);
407 chars12 lines
main.cs// Create the color attachment. VkAttachmentDescription color_attachment = new VkAttachmentDescription { format = swap_chain_image_format, samples = VkSampleCountFlags.SampleCountFlags1, loadOp = VkAttachmentLoadOp.Clear, storeOp = VkAttachmentStoreOp.Store, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.Undefined, finalLayout = VkImageLayout.PresentSrcKHR, }; // Create the attachment reference. VkAttachmentReference color_attachment_reference = new VkAttachmentReference { attachment = 0, layout = VkImageLayout.ColorAttachmentOptimal, }; // Create the subpass. VkSubpassDescription subpass = new VkSubpassDescription { pipelineBindPoint = VkPipelineBindPoint.Graphics, colorAttachmentCount = 1, pColorAttachments = &color_attachment_reference, }; // Create the render pass. VkRenderPass render_pass = device.CreateRenderPass(subpass);
971 chars31 lines
main.cs// Define the triangle vertices. float[] triangle_vertices = new float[] { 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, }; // Create the vertex buffer. VkBufferCreateInfo vertex_buffer_create_info = new VkBufferCreateInfo { sType = VkStructureType.StructureTypeBufferCreateInfo, size = sizeof(float) * 9, usage = VkBufferUsageFlags.BufferUsageVertexBufferBit, }; VkBuffer vertex_buffer = device.CreateBuffer(vertex_buffer_create_info); // Allocate memory for the vertex buffer. VkMemoryRequirements vertex_buffer_requirements = vertex_buffer.GetMemoryRequirements(); int vertex_buffer_index = physical_device.FindMemoryType( vertex_buffer_requirements.memoryTypeBits, VkMemoryPropertyFlags.MemoryPropertyHostVisibleBit | VkMemoryPropertyFlags.MemoryPropertyHostCoherentBit); VkMemoryAllocateInfo vertex_buffer_allocate_info = new VkMemoryAllocateInfo { sType = VkStructureType.StructureTypeMemoryAllocateInfo, allocationSize = vertex_buffer_requirements.size, memoryTypeIndex = vertex_buffer_index, }; VkDeviceMemory vertex_buffer_memory = device.AllocateMemory(vertex_buffer_allocate_info); // Bind the vertex buffer memory. device.BindBufferMemory(vertex_buffer, vertex_buffer_memory); // Copy the triangle vertices to the vertex buffer. IntPtr vertex_buffer_data_ptr = device.MapMemory(vertex_buffer_memory, 0, vertex_buffer_create_info.size, VkMemoryMapFlags.MemoryMapWriteBit); var vertex_buffer_data = new float[] { 0.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, }; Marshal.Copy(vertex_buffer_data, 0, vertex_buffer_data_ptr, vertex_buffer_create_info.size); device.UnmapMemory(vertex_buffer_memory);
1682 chars43 lines
main.cs// Define the vertex input state. VkVertexInputBindingDescription vertex_binding_description = new VkVertexInputBindingDescription { binding = 0, stride = sizeof(float) * 3, inputRate = VkVertexInputRate.VertexInputRateVertex, }; VkVertexInputAttributeDescription[] vertex_attribute_descriptions = new VkVertexInputAttributeDescription[] { new VkVertexInputAttributeDescription { location = 0, binding = 0, format = VkFormat.FormatR32G32B32Sfloat, offset = 0, }, }; VkPipelineVertexInputStateCreateInfo vertex_input_state_create_info = new VkPipelineVertexInputStateCreateInfo { sType = VkStructureType.StructureTypePipelineVertexInputStateCreateInfo, vertexBindingDescriptionCount = 1, pVertexBindingDescriptions = &vertex_binding_description, vertexAttributeDescriptionCount = 1, pVertexAttributeDescriptions = vertex_attribute_descriptions, }; // Define the input assembly state. VkPipelineInputAssemblyStateCreateInfo input_assembly_state_create_info = new VkPipelineInputAssemblyStateCreateInfo { sType = VkStructureType.StructureTypePipelineInputAssemblyStateCreateInfo, topology = VkPrimitiveTopology.PrimitiveTopologyTriangleList, primitiveRestartEnable = false, }; // Define the viewport state. VkPipelineViewportStateCreateInfo viewport_state_create_info = new VkPipelineViewportStateCreateInfo { sType = VkStructureType.StructureTypePipelineViewportStateCreateInfo, viewportCount = 1, pViewports = new VkViewport[] { new VkViewport { x = 0, y = 0, width = swap_chain_extent.width, height = swap_chain_extent.height, minDepth = 0, maxDepth = 1 } }, scissorCount = 1, pScissors = new VkRect2D[] { new VkRect2D { offset = new VkOffset2D { x = 0, y = 0 }, extent = swap_chain_extent } }, }; // Define the rasterization state. VkPipelineRasterizationStateCreateInfo rasterization_state_create_info = new VkPipelineRasterizationStateCreateInfo { sType = VkStructureType.StructureTypePipelineRasterizationStateCreateInfo, depthClampEnable = false, rasterizerDiscardEnable = false, polygonMode = VkPolygonMode.PolygonModeFill, lineWidth = 1.0f, cullMode = VkCullModeFlags.CullModeNone, frontFace = VkFrontFace.FrontFaceCounterClockwise, depthBiasEnable = false, }; // Define the multisample state. VkPipelineMultisampleStateCreateInfo multisample_state_create_info = new VkPipelineMultisampleStateCreateInfo { sType = VkStructureType.StructureTypePipelineMultisampleStateCreateInfo, rasterizationSamples = VkSampleCountFlags.SampleCountFlags1, sampleShadingEnable = false, }; // Define the color blend state. VkPipelineColorBlendAttachmentState color_blend_attachment_state = new VkPipelineColorBlendAttachmentState { colorWriteMask = VkColorComponentFlags.ColorComponentRBit | VkColorComponentFlags.ColorComponentGBit | VkColorComponentFlags.ColorComponentBBit, blendEnable = false, }; VkPipelineColorBlendStateCreateInfo color_blend_state_create_info = new VkPipelineColorBlendStateCreateInfo { sType = VkStructureType.StructureTypePipelineColorBlendStateCreateInfo, logicOpEnable = false, logicOp = VkLogicOp.LogicOpCopy, attachmentCount = 1, pAttachments = &color_blend_attachment_state, }; // Define the pipeline layout. VkPipelineLayoutCreateInfo pipeline_layout_create_info = new VkPipelineLayoutCreateInfo { sType = VkStructureType.StructureTypePipelineLayoutCreateInfo, }; VkPipelineLayout pipeline_layout = device.CreatePipelineLayout(pipeline_layout_create_info); // Define the shader stages. VkShaderModule vertex_shader_module = device.CreateShaderModule(vertex_shader_code); VkShaderModule fragment_shader_module = device.CreateShaderModule(fragment_shader_code); VkPipelineShaderStageCreateInfo vertex_shader_stage_create_info = new VkPipelineShaderStageCreateInfo { sType = VkStructureType.StructureTypePipelineShaderStageCreateInfo, stage = VkShaderStageFlags.ShaderStageVertexBit, module = vertex_shader_module, pName = "main", }; VkPipelineShaderStageCreateInfo fragment_shader_stage_create_info = new VkPipelineShaderStageCreateInfo { sType = VkStructureType.StructureTypePipelineShaderStageCreateInfo, stage = VkShaderStageFlags.ShaderStageFragmentBit, module = fragment_shader_module, pName = "main", }; VkPipelineShaderStageCreateInfo[] shader_stages_create_info = new VkPipelineShaderStageCreateInfo[] { vertex_shader_stage_create_info, fragment_shader_stage_create_info, }; // Create the graphics pipeline. VkGraphicsPipelineCreateInfo graphics_pipeline_create_info = new VkGraphicsPipelineCreateInfo { sType = VkStructureType.StructureTypeGraphicsPipelineCreateInfo, stageCount = (uint)shader_stages_create_info.Length, pStages = shader_stages_create_info, pVertexInputState = &vertex_input_state_create_info, pInputAssemblyState = &input_assembly_state_create_info, pViewportState = &viewport_state_create_info, pRasterizationState = &rasterization_state_create_info, pMultisampleState = &multisample_state_create_info, pColorBlendState = &color_blend_state_create_info, layout = pipeline_layout, renderPass = render_pass, subpass = 0, }; VkPipeline graphics_pipeline = device.CreateGraphicsPipelines(VkPipelineCache.Null, new VkGraphicsPipelineCreateInfo[] { graphics_pipeline_create_info })[0]; // Destroy the shader modules. device.DestroyShaderModule(vertex_shader_module); device.DestroyShaderModule(fragment_shader_module);
5549 chars140 lines
main.cs// Begin the command buffer. VkCommandBuffer command_buffer = device.AllocateCommandBuffers(new VkCommandBufferAllocateInfo(VkCommandPool.Null, VkCommandBufferLevel.CommandBufferLevelPrimary, 1))[0]; VkCommandBufferBeginInfo command_buffer_begin_info = new VkCommandBufferBeginInfo(VkCommandBufferUsageFlags.CommandBufferUsageSimultaneousUseBit); command_buffer.Begin(command_buffer_begin_info); // Define the render pass parameters. VkClearValue clear_color = new VkClearValue(new VkClearColorValue(0.0f, 0.0f, 0.0f, 0.0f)); VkRenderPassBeginInfo render_pass_begin_info = new VkRenderPassBeginInfo(render_pass, VkFramebuffer.Null, new VkRect2D(new VkOffset2D(0, 0), swap_chain_extent), clear_color); command_buffer.CmdBeginRenderPass(render_pass_begin_info, VkSubpassContents.SubpassContentsInline); // Bind the graphics pipeline. command_buffer.CmdBindPipeline(VkPipelineBindPoint.PipelineBindPointGraphics, graphics_pipeline); // Bind the vertex buffer. VkDeviceSize vertex_buffer_offset = 0; command_buffer.CmdBindVertexBuffers(0, new VkBuffer[] { vertex_buffer }, new VkDeviceSize[] { vertex_buffer_offset }); // Draw the triangle. command_buffer.CmdDraw(3, 1, 0, 0); // End the render pass. command_buffer.CmdEndRenderPass(); // End the command buffer. command_buffer.End();
1288 chars27 lines
main.cs// Submit the command buffer to the queue. VkSemaphore image_available_semaphore = device.CreateSemaphore(); VkSemaphore render_finished_semaphore = device.CreateSemaphore(); VkPipelineStageFlags[] wait_dst_stage_mask = new VkPipelineStageFlags[] { VkPipelineStageFlags.PipelineStageColorAttachmentOutputBit }; VkSubmitInfo submit_info = new VkSubmitInfo { sType = VkStructureType.StructureTypeSubmitInfo, waitSemaphoreCount = 1, pWaitSemaphores = new VkSemaphore[] { image_available_semaphore }, pWaitDstStageMask = wait_dst_stage_mask, commandBufferCount = 1, pCommandBuffers = new VkCommandBuffer[] { command_buffer }, signalSemaphoreCount = 1, pSignalSemaphores = new VkSemaphore[] { render_finished_semaphore }, }; queue.Submit(new VkSubmitInfo[] { submit_info }); // Present the rendered image. VkPresentInfoKHR present_info = new VkPresentInfoKHR { sType = VkStructureType.StructureTypePresentInfoKHR, waitSemaphoreCount = 1, pWaitSemaphores = new VkSemaphore[] { render_finished_semaphore }, swapchainCount = 1, pSwapchains = new VkSwapchainKHR[] { swap_chain }, pImageIndices = new uint[] { 0 }, }; queue.PresentKHR(present_info);
1201 chars33 lines
main.csdevice.WaitIdle(); device.DestroySemaphore(image_available_semaphore); device.DestroySemaphore(render_finished_semaphore); device.DestroyPipelineLayout(pipeline_layout); device.DestroyPipeline(graphics_pipeline); device.FreeMemory(vertex_buffer_memory); device.DestroyBuffer(vertex_buffer); device.DestroyRenderPass(render_pass); device.DestroySwapchainKHR(swap_chain); device.Destroy(); instance.Destroy();
415 chars19 lines
gistlibby LogSnag