public Triangle() { InitializeComponent(); InitializeVulkan(); _Bitmap = new Bitmap(640, 480); _Framebuffer = new Framebuffer(_Device, 640, 480); VkPipelineLayout dummyLayout = _Device.CreatePipelineLayout(VkPipelineLayoutCreateFlag.NONE, null, null); _VertexShader = _Device.CreateShaderModule(VkShaderModuleCreateFlag.NONE, System.IO.File.ReadAllBytes("./Shaders/vertexShader.spv")); _FramgemtShader = _Device.CreateShaderModule(VkShaderModuleCreateFlag.NONE, System.IO.File.ReadAllBytes("./Shaders/fragmentShader.spv")); _GraphicsPipeline = new Pipeline(_Framebuffer, dummyLayout, _VertexShader, "main", _FramgemtShader, "main"); // Finally we will need a fence for our submission in order to wait on it _Fence = _Device.CreateFence(VkFenceCreateFlag.NONE); // VkBuffer indexBuffer = _Device.CreateBuffer(0, 3 * sizeof(Int32), VkBufferUsageFlag.VK_BUFFER_USAGE_INDEX_BUFFER, VkSharingMode.VK_SHARING_MODE_CONCURRENT, new VkQueueFamilyProperties[] { _Queue.Family }); // VkBuffer vertexBuffer = _Device.CreateBuffer(0, 3 * sizeof(float), VkBufferUsageFlag.VK_BUFFER_USAGE_VERTEX_BUFFER, VkSharingMode.VK_SHARING_MODE_CONCURRENT, new VkQueueFamilyProperties[] { _Queue.Family }); // Now we need to create a command buffer and we will fill it with a single command: // Fill the image with the color (0.1f, 0.75f, 1.0f, 1.0f) which is a Sky blue. VkClearValue.VkClearColorValue.Float color = new VkClearValue.VkClearColorValue.Float(); color.float32[0] = 0.1f; color.float32[1] = 0.75f; color.float32[2] = 1.0f; color.float32[3] = 1.0f; VkCommandPool Pool = _Device.CreateCommandPool(VkCommandPoolCreateFlag.NONE, _Queue.Family); _CommandBuffer = Pool.AllocateCommandBuffer(VkCommandBufferLevel.VK_COMMAND_BUFFER_LEVEL_PRIMARY); _CommandBuffer.Begin(VkCommandBufferUsageFlag.NONE); _CommandBuffer.CmdBeginRenderPass(_Framebuffer.RenderPass, new VkRect2D(0, 0, (uint)640, (uint)480), _Framebuffer.GetFramebuffer(), new VkClearValue[] { color }, VkSubpassContents.VK_SUBPASS_CONTENTS_INLINE); _GraphicsPipeline.BindPipeline(_CommandBuffer); _CommandBuffer.CmdDraw(3, 1, 0, 0); _CommandBuffer.CmdEndRenderPass(); _CommandBuffer.cmdCopyImageToBuffer(_Framebuffer.FrameBufferColor, VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, _Framebuffer._TransferBuffer, new VkBufferImageCopy[] { new VkBufferImageCopy() { bufferImageHeight = (uint)_Framebuffer.Height, bufferOffset = 0, bufferRowLength = (uint)_Framebuffer.Width, imageExtent = new VkExtent3D() { depth = 1, width = (uint)_Framebuffer.Width, height = (uint)_Framebuffer.Height }, imageSubresource = new VkImageSubresourceLayers() { aspectMask = VkImageAspectFlag.VK_IMAGE_ASPECT_COLOR_BIT, baseArrayLayer = 0, layerCount = 1, mipLevel = 0 } } }); _CommandBuffer.End(); }
void RecordCommands() { for (int i = 0; i < swapchainImages.Count; i++) { VkCommandBuffer commandBuffer = commandBuffers[i]; commandBuffer.Reset(VkCommandBufferResetFlags.None); VkCommandBufferBeginInfo beginInfo = new VkCommandBufferBeginInfo(); beginInfo.flags = VkCommandBufferUsageFlags.SimultaneousUseBit; commandBuffer.Begin(beginInfo); //transfer to writable commandBuffer.PipelineBarrier(VkPipelineStageFlags.FragmentShaderBit, VkPipelineStageFlags.TransferBit, VkDependencyFlags.None, null, null, new List <VkImageMemoryBarrier> { new VkImageMemoryBarrier { image = textureImage, oldLayout = VkImageLayout.ShaderReadOnlyOptimal, newLayout = VkImageLayout.TransferDstOptimal, srcQueueFamilyIndex = -1, //VK_QUEUE_FAMILY_IGNORED dstQueueFamilyIndex = -1, srcAccessMask = VkAccessFlags.None, dstAccessMask = VkAccessFlags.TransferWriteBit, subresourceRange = new VkImageSubresourceRange { aspectMask = VkImageAspectFlags.ColorBit, baseArrayLayer = 0, layerCount = 1, baseMipLevel = 0, levelCount = 1 } } }); commandBuffer.CopyBufferToImage(stagingBuffer, textureImage, VkImageLayout.TransferDstOptimal, new VkBufferImageCopy[] { new VkBufferImageCopy { imageExtent = new VkExtent3D { width = imageWidth, height = imageHeight, depth = 1 }, imageSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.ColorBit, baseArrayLayer = 0, layerCount = 1, mipLevel = 0 } } }); //transfer to shader readable commandBuffer.PipelineBarrier(VkPipelineStageFlags.TransferBit, VkPipelineStageFlags.FragmentShaderBit, VkDependencyFlags.None, null, null, new List <VkImageMemoryBarrier> { new VkImageMemoryBarrier { image = textureImage, oldLayout = VkImageLayout.TransferDstOptimal, newLayout = VkImageLayout.ShaderReadOnlyOptimal, srcQueueFamilyIndex = -1, //VK_QUEUE_FAMILY_IGNORED dstQueueFamilyIndex = -1, srcAccessMask = VkAccessFlags.TransferWriteBit, dstAccessMask = VkAccessFlags.ShaderReadBit, subresourceRange = new VkImageSubresourceRange { aspectMask = VkImageAspectFlags.ColorBit, baseArrayLayer = 0, layerCount = 1, baseMipLevel = 0, levelCount = 1 } } }); VkRenderPassBeginInfo renderPassBeginInfo = new VkRenderPassBeginInfo(); renderPassBeginInfo.renderPass = renderPass; renderPassBeginInfo.framebuffer = swapchainFramebuffers[i]; renderPassBeginInfo.renderArea = new VkRect2D { extent = new VkExtent2D { width = window.FramebufferWidth, height = window.FramebufferHeight } }; renderPassBeginInfo.clearValues = new List <VkClearValue> { new VkClearValue { color = new VkClearColorValue(0.125f, 0.125f, 0.125f, 0.125f) } }; commandBuffer.BeginRenderPass(renderPassBeginInfo, VkSubpassContents.Inline); commandBuffer.BindPipeline(VkPipelineBindPoint.Graphics, pipeline); commandBuffer.BindDescriptorSets(VkPipelineBindPoint.Graphics, pipelineLayout, 0, descriptorSet, null); commandBuffer.BindVertexBuffers(0, vertexBuffer, 0); commandBuffer.BindIndexBuffer(indexBuffer, 0, VkIndexType.UINT32); commandBuffer.SetViewports(0, new VkViewport { width = swapchainExtent.width, height = swapchainExtent.height, minDepth = 0, maxDepth = 1, }); commandBuffer.SetScissor(0, new VkRect2D { extent = swapchainExtent }); commandBuffer.DrawIndexed(6, 1, 0, 0, 0); commandBuffer.EndRenderPass(); commandBuffer.End(); } }
public ClearImage() { InitializeComponent(); _Bitmap = new Bitmap(640, 480); // Create the VUlkan instance that we will use for this app _Instance = new VkInstance("ClearImage - Sample", 1, "Ratchet", 1); // Now lets walk all physical device and find the first one that supports graphics queue foreach (VkPhysicalDevice physicalDevice in _Instance.vkEnumeratePhysicalDevices()) { foreach (VkQueueFamilyProperties queueFamilly in physicalDevice.QueueFamilies) { if ((queueFamilly.queueFlags & VkQueueFlags.VK_QUEUE_GRAPHICS) != 0) { // We have a physical device that supports graphics queue, we can now create a Device on it // with one queue and use it as our main device for this sample _Device = physicalDevice.CreateDevice(new VkDeviceQueueCreateInfo[] { new VkDeviceQueueCreateInfo() { queueCount = 1, queueFamily = queueFamilly, queuePriorities = new float[] { 1.0f } } }); // Ok now lets grab the graphics queue back. Technically there should only be one // But just to be clean we do an iteration and look for the queue that matches our // need foreach (VkQueue queue in _Device.Queues) { if (queue.Family.queueFlags == queueFamilly.queueFlags) { _Queue = queue; break; } } // Now it is time to create the image that we will fill wih the solid color _Image = _Device.CreateImage( VkImageCreateFlag.NONE, VkFormat.VK_FORMAT_B8G8R8A8_SRGB, _Bitmap.Width, _Bitmap.Height, 1, 1, VkSampleCountFlag.VK_SAMPLE_COUNT_1, VkImageTiling.VK_IMAGE_TILING_LINEAR, VkImageUsageFlag.VK_IMAGE_USAGE_TRANSFER_SRC | VkImageUsageFlag.VK_IMAGE_USAGE_TRANSFER_DST, VkSharingMode.VK_SHARING_MODE_EXCLUSIVE, null, VkImageLayout.VK_IMAGE_LAYOUT_GENERAL); // We will back this image with Host Accessible Memomy so we can map it an copy // the content from the Host. // To do so we need to find the right memory type first. VkMemoryType HostMemory = new VkMemoryType(); foreach (VkMemoryType memoryType in _Image.MemoryRequirements.memoryTypes) { // Pick the first memory type that can be mapped into host memory if ((memoryType.propertyFlags & VkMemoryPropertyFlags.VK_MEMORY_PROPERTY_HOST_VISIBLE) != 0) { HostMemory = memoryType; break; } } // Allocate the backing memory for this image VkDeviceMemory Memory = _Device.AllocateMemory(_Image.MemoryRequirements.size, HostMemory); _Image.BindMemory(Memory, 0); // Create the CPU mapping _ImagePtr = Memory.Map(0, _Image.MemoryRequirements.size, VkMemoryMapFlag.NONE); // Now we need to create a command buffer and we will fill it with a single command: // Fill the image with the color (0.1f, 0.75f, 1.0f, 1.0f) which is a Sky blue. VkCommandPool Pool = _Device.CreateCommandPool(VkCommandPoolCreateFlag.NONE, _Queue.Family); _CommandBuffer = Pool.AllocateCommandBuffer(VkCommandBufferLevel.VK_COMMAND_BUFFER_LEVEL_PRIMARY); _CommandBuffer.Begin(VkCommandBufferUsageFlag.NONE); _CommandBuffer.CmdClearColorImage( _Image, VkImageLayout.VK_IMAGE_LAYOUT_GENERAL, 0.1f, 0.75f, 1.0f, 1.0f, new VkImageSubresourceRange[] { new VkImageSubresourceRange() { aspectMask = VkImageAspectFlag.VK_IMAGE_ASPECT_COLOR_BIT, baseArrayLayer = 0, baseMipLevel = 0, layerCount = 1, levelCount = 1 } }); _CommandBuffer.End(); // Finally we will need a fence for our submission in order to wait on it _Fence = _Device.CreateFence(VkFenceCreateFlag.NONE); break; } } } }