void Render(Queue queue, CommandPool cmdPool, VertexData vertexData, ImageData imageData, Buffer imageBuffer, RenderPass renderPass, Pipeline pipeline, Framebuffer framebuffer) { uint width = imageData.Width; uint height = imageData.Height; var cmdBuffers = AllocateCommandBuffers(cmdPool, 1); var cmdBuffer = cmdBuffers[0]; var beginInfo = new CommandBufferBeginInfo(); cmdBuffer.Begin(beginInfo); // CommandBuffer Begin PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.Preinitialized, ImageLayout.ColorAttachmentOptimal, AccessFlags.HostWrite, AccessFlags.ColorAttachmentWrite); var clearRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1); cmdBuffer.ClearColorImage(imageData.Image, ImageLayout.TransferDstOptimal, new ClearColorValue(), new[] { clearRange }); RenderTriangle(cmdBuffer, vertexData, renderPass, pipeline, framebuffer, width, height); // Prepare the render target for copying PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.ColorAttachmentOptimal, ImageLayout.TransferSrcOptimal, AccessFlags.ColorAttachmentWrite, AccessFlags.TransferRead); // Copy the render target image to a buffer CopyImageToBuffer(cmdBuffer, imageData, imageBuffer, width, height); // End recording commands to the buffer cmdBuffer.End(); SubmitForExecution(queue, cmdBuffer); queue.WaitIdle(); // wait for execution to finish device.FreeCommandBuffers(cmdPool, new[] { cmdBuffer }); }
void CopyBufferToImage(Queue queue, CommandPool cmdPool, ImageData imageData, Buffer imageBuffer) { var cmdBuffers = AllocateCommandBuffers(cmdPool, 1); var cmdBuffer = cmdBuffers[0]; var beginInfo = new CommandBufferBeginInfo(); cmdBuffer.Begin(beginInfo); PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.Preinitialized, ImageLayout.TransferDstOptimal, AccessFlags.HostWrite, AccessFlags.TransferWrite); var subresource = new ImageSubresourceLayers(ImageAspectFlags.Color, 0, 0, 1); var imageCopy = new BufferImageCopy(0, 0, 0, subresource, new Offset3D(0, 0, 0), new Extent3D(imageData.Width, imageData.Height, 1)); cmdBuffer.CopyBufferToImage(imageBuffer, imageData.Image, ImageLayout.TransferDstOptimal, new BufferImageCopy[] { imageCopy }); PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.TransferDstOptimal, ImageLayout.ColorAttachmentOptimal, AccessFlags.TransferWrite, AccessFlags.ColorAttachmentWrite); cmdBuffer.End(); var submitInfo = new SubmitInfo(null, null, new[] { cmdBuffer }, null); queue.Submit(new[] { submitInfo }); submitInfo.Dispose(); queue.WaitIdle(); device.FreeCommandBuffers(cmdPool, new[] { cmdBuffer }); }
public unsafe void Begin(ref CommandBufferBeginInfo beginInfo) { fixed (CommandBufferBeginInfo* __beginInfo__ = &beginInfo) { vkBeginCommandBuffer(this, __beginInfo__).CheckError(); } }
CommandBuffer [] CreateCommandBuffers(Image [] images, Framebuffer [] framebuffers, RenderPass renderPass, SurfaceCapabilitiesKhr surfaceCapabilities) { var createPoolInfo = new CommandPoolCreateInfo { Flags = CommandPoolCreateFlags.ResetCommandBuffer }; var commandPool = device.CreateCommandPool(createPoolInfo); var commandBufferAllocateInfo = new CommandBufferAllocateInfo { Level = CommandBufferLevel.Primary, CommandPool = commandPool, CommandBufferCount = (uint)images.Length }; var buffers = device.AllocateCommandBuffers(commandBufferAllocateInfo); for (int i = 0; i < images.Length; i++) { var commandBufferBeginInfo = new CommandBufferBeginInfo(); buffers [i].Begin(commandBufferBeginInfo); var renderPassBeginInfo = new RenderPassBeginInfo { Framebuffer = framebuffers [i], RenderPass = renderPass, ClearValues = new ClearValue [] { new ClearValue { Color = new ClearColorValue(new float [] { 0.9f, 0.7f, 0.0f, 1.0f }) } }, RenderArea = new Rect2D { Extent = surfaceCapabilities.CurrentExtent } }; buffers [i].CmdBeginRenderPass(renderPassBeginInfo, SubpassContents.Inline); buffers [i].CmdEndRenderPass(); buffers [i].End(); } return(buffers); }
void CreateCommandBuffer() { /* * We are getting closer to the end. In order to send commands to the device(GPU), * we must first record commands into a command buffer. * To allocate a command buffer, we must first create a command pool. So let us do that. */ CommandPoolCreateInfo commandPoolCreateInfo = new CommandPoolCreateInfo() { Flags = 0, // the queue family of this command pool. All command buffers allocated from this command pool, // must be submitted to queues of this family ONLY. QueueFamilyIndex = computeQueueFamilyIndex }; commandPool = device.CreateCommandPool(commandPoolCreateInfo); /* * Now allocate a command buffer from the command pool. */ CommandBufferAllocateInfo commandBufferAllocateInfo = new CommandBufferAllocateInfo() { //commandBufferAllocateInfo.commandPool = commandPool; // specify the command pool to allocate from. // if the command buffer is primary, it can be directly submitted to queues. // A secondary buffer has to be called from some primary command buffer, and cannot be directly // submitted to a queue. To keep things simple, we use a primary command buffer. Level = CommandBufferLevel.Primary, // VK_COMMAND_BUFFER_LEVEL_PRIMARY; CommandBufferCount = 1 // allocate a single command buffer. }; commandBuffers = commandPool.AllocateBuffers(commandBufferAllocateInfo); // allocate command buffer. /* * Now we shall start recording commands into the newly allocated command buffer. */ CommandBufferBeginInfo beginInfo = new CommandBufferBeginInfo() { Flags = CommandBufferUsages.OneTimeSubmit// VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; // the buffer is only submitted and used once in this application. }; commandBuffers[0].Begin(beginInfo); // start recording commands. /* * We need to bind a pipeline, AND a descriptor set before we dispatch. * The validation layer will NOT give warnings if you forget these, so be very careful not to forget them. */ commandBuffers[0].CmdBindPipeline(PipelineBindPoint.Compute, pipelines[0]); // VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); commandBuffers[0].CmdBindDescriptorSets(PipelineBindPoint.Compute, pipelineLayout, 0, new[] { descriptorSet }); // VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); /* * Calling vkCmdDispatch basically starts the compute pipeline, and executes the compute shader. * The number of workgroups is specified in the arguments. * If you are already familiar with compute shaders from OpenGL, this should be nothing new to you. */ commandBuffers[0].CmdDispatch((int)Math.Ceiling((double)(WIDTH / WORKGROUP_SIZE)), (int)Math.Ceiling((double)(HEIGHT / WORKGROUP_SIZE)), 1); commandBuffers[0].End(); // end recording commands. }
public void Begin(CommandBufferBeginInfo pBeginInfo) { Result result; unsafe { result = Interop.NativeMethods.vkBeginCommandBuffer(this.m, pBeginInfo != null ? pBeginInfo.m : (Interop.CommandBufferBeginInfo *) default(IntPtr)); if (result != Result.Success) { throw new ResultException(result); } } }
public void BeginRecording() { if (!_hasStarted) { _hasStarted = true; var beginInfo = new CommandBufferBeginInfo { SType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.CommandBufferUsageOneTimeSubmitBit }; _device.Api.BeginCommandBuffer(InternalHandle, beginInfo); } }
protected static void BeginCommandBuffer(CommandBuffer buffer, CommandBufferUsageFlags flags, CommandBufferInheritanceInfo *inheritInfo) { var info = new CommandBufferBeginInfo { SType = StructureType.CommandBufferBeginInfo, Flags = flags, PInheritanceInfo = inheritInfo }; var res = VkApi.BeginCommandBuffer(buffer, &info); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Failed to begin Command Buffer recording!", res); } }
public void CopyBuffer(string queue, string src, string dest, int size) { if (!mBuffers.ContainsKey(src)) { Misc.SafeInvoke(eErrorSpam, "No buffer named: " + src + "..."); return; } if (!mBuffers.ContainsKey(dest)) { Misc.SafeInvoke(eErrorSpam, "No buffer named: " + dest + "..."); return; } if (!mCommandPools.ContainsKey(queue)) { Misc.SafeInvoke(eErrorSpam, "No pool named: " + queue + "..."); return; } CommandBufferAllocateInfo cbai = new CommandBufferAllocateInfo(); cbai.Level = CommandBufferLevel.Primary; cbai.CommandBufferCount = 1; CommandBuffer [] bufs = mCommandPools[queue].AllocateBuffers(cbai); CommandBufferBeginInfo cbbi = new CommandBufferBeginInfo( CommandBufferUsages.OneTimeSubmit); bufs[0].Begin(cbbi); BufferCopy bc = new BufferCopy(size, 0, 0); bufs[0].CmdCopyBuffer(mBuffers[src], mBuffers[dest], bc); bufs[0].End(); SubmitInfo si = new SubmitInfo(); si.CommandBuffers = new IntPtr[] { bufs[0].Handle }; SubmitToQueue(si, queue, null); mQueueNames[queue].WaitIdle(); bufs[0].Dispose(); }
private void CreateCommandBuffers() { var allocInfo = new CommandBufferAllocateInfo() { CommandPool = vkCommandPool, Level = CommandBufferLevel.Primary, CommandBufferCount = (uint)vkSwapChainFramebuffers.Length, }; vkCommandBuffers = vkDevice.AllocateCommandBuffers(allocInfo); for (int i = 0; i < vkCommandBuffers.Length; i++) { var beginInfo = new CommandBufferBeginInfo() { Flags = CommandBufferUsageFlags.SimultaneousUse, InheritanceInfo = null, }; var buffer = vkCommandBuffers[i]; buffer.Begin(beginInfo); var renderPassInfo = new RenderPassBeginInfo() { RenderPass = vkRenderPass, Framebuffer = vkSwapChainFramebuffers[i], RenderArea = new Rect2D() { Extent = vkSwapChainExtent }, ClearValues = new ClearValue[] { new ClearValue() { Color = new ClearColorValue(new float[] { 0.0f, 0.0f, 0.0f, 1.0f }) } }, }; buffer.CmdBeginRenderPass(renderPassInfo, SubpassContents.Inline); buffer.CmdBindPipeline(PipelineBindPoint.Graphics, vkGraphicsPipeline); buffer.CmdBindDescriptorSet(PipelineBindPoint.Graphics, vkPipelineLayout, 0, vkDescriptorSet, 0); buffer.CmdBindVertexBuffer(0, vkVertexBuffer, 0); buffer.CmdBindIndexBuffer(vkIndexBuffer, 0, IndexType.Uint16); buffer.CmdDrawIndexed((uint)indices.Length, 1, 0, 0, 0); buffer.CmdEndRenderPass(); buffer.End(); } }
protected override void InitCommandBuffers() { for (int i = 0; i < bufferSize; i++) { var beginInfo = new CommandBufferBeginInfo { Flags = CommandBufferUsageFlags.SimultaneousUse }; commandBuffers[i].Begin(beginInfo); var clearColor = new ClearValue { Color = new ClearColorValue(new float[] { 25 / 255f, 0.0f, 10 / 255f, 1.0f }) }; var renderPassInfo = new RenderPassBeginInfo { RenderPass = renderPass, Framebuffer = framebuffers[i], RenderArea = new Rect2D { Offset = new Offset2D { X = 0, Y = 0 }, Extent = extent }, ClearValueCount = 1, ClearValues = new ClearValue[] { clearColor } }; commandBuffers[i].CmdBeginRenderPass(renderPassInfo, SubpassContents.Inline); commandBuffers[i].CmdBindPipeline(PipelineBindPoint.Graphics, graphicsPipeline); commandBuffers[i].CmdBindVertexBuffer(0, vertexBuffer, 0); commandBuffers[i].CmdBindIndexBuffer(indexBuffer, 0, IndexType.Uint32); commandBuffers[i].CmdBindDescriptorSet(PipelineBindPoint.Graphics, pipelineLayout, 0, descriptorSets[i], null); commandBuffers[i].CmdDrawIndexed((uint)mesh.indices.Length, 1, 0, 0, 0); commandBuffers[i].CmdEndRenderPass(); commandBuffers[i].End(); } }
public void BeginBuffer(CommandBuffer cb, int frameBufIndex, ClearValue cv) { CommandBufferBeginInfo cbbi = new CommandBufferBeginInfo(); cbbi.Flags = CommandBufferUsages.SimultaneousUse; cb.Begin(cbbi); RenderPassBeginInfo rpbi = new RenderPassBeginInfo( mChainBuffers[frameBufIndex], new Rect2D(Offset2D.Zero, mDevices.GetChainExtent()), cv); //rpbi.ClearValues =cv; cb.CmdBeginRenderPass(rpbi); cb.CmdBindPipeline(PipelineBindPoint.Graphics, mPipe); }
void CreateCommandBuffer(CommandBuffer cmdBuffer, VertexData vertexData, RenderPass renderPass, PipelineLayout pipelineLayout, Pipeline pipeline, DescriptorSet descriptorSet, ImageData swapchainImageData, Framebuffer framebuffer) { var beginInfo = new CommandBufferBeginInfo(); cmdBuffer.Begin(beginInfo); beginInfo.Dispose(); PipelineBarrierSetLayout(cmdBuffer, swapchainImageData.Image, ImageLayout.PresentSrcKHR, ImageLayout.ColorAttachmentOptimal, AccessFlags.MemoryRead, AccessFlags.ColorAttachmentWrite); var clearRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1); cmdBuffer.ClearColorImage(swapchainImageData.Image, ImageLayout.TransferDstOptimal, new ClearColorValue(), new[] { clearRange }); RenderTexturedQuad(cmdBuffer, vertexData, swapchainImageData, pipelineLayout, descriptorSet, renderPass, pipeline, framebuffer, swapchainImageData.Width, swapchainImageData.Height); PipelineBarrierSetLayout(cmdBuffer, swapchainImageData.Image, ImageLayout.ColorAttachmentOptimal, ImageLayout.PresentSrcKHR, AccessFlags.ColorAttachmentWrite, AccessFlags.MemoryRead); cmdBuffer.End(); }
List <ImageData> InitializeSwapchainImages(Queue queue, CommandPool cmdPool, Image[] images, Format imageFormat) { var cmdBuffers = AllocateCommandBuffers(cmdPool, 1); var cmdBuffer = cmdBuffers.First(); var inheritanceInfo = new CommandBufferInheritanceInfo(); var beginInfo = new CommandBufferBeginInfo { InheritanceInfo = inheritanceInfo }; cmdBuffer.Begin(beginInfo); foreach (var img in images) { PipelineBarrierSetLayout(cmdBuffer, img, ImageLayout.Undefined, ImageLayout.PresentSrcKHR, AccessFlags.None, AccessFlags.None); } cmdBuffer.End(); var submitInfo = new SubmitInfo(null, null, new[] { cmdBuffer }, null); queue.Submit(new[] { submitInfo }); queue.WaitIdle(); device.FreeCommandBuffers(cmdPool, new[] { cmdBuffer }); var imageDatas = new List <ImageData>(); foreach (var img in images) { var imgData = new ImageData(); imgData.Image = img; imgData.Width = 800; imgData.Height = 600; imgData.View = CreateImageView(img, imageFormat); imageDatas.Add(imgData); } return(imageDatas); }
CommandBuffer [] CreateCommandBuffers(Image [] images, Framebuffer [] framebuffers, Pipeline pipeline, Buffer vertexBuffer, Buffer indexBuffer, uint indexLength) { var createPoolInfo = new CommandPoolCreateInfo { Flags = CommandPoolCreateFlags.ResetCommandBuffer }; var commandPool = device.CreateCommandPool(createPoolInfo); var commandBufferAllocateInfo = new CommandBufferAllocateInfo { Level = CommandBufferLevel.Primary, CommandPool = commandPool, CommandBufferCount = (uint)images.Length }; var buffers = device.AllocateCommandBuffers(commandBufferAllocateInfo); var commandBufferBeginInfo = new CommandBufferBeginInfo(); for (int i = 0; i < images.Length; i++) { buffers [i].Begin(commandBufferBeginInfo); var renderPassBeginInfo = new RenderPassBeginInfo { Framebuffer = framebuffers [i], RenderPass = renderPass, ClearValues = new ClearValue [] { new ClearValue { Color = new ClearColorValue(new float [] { 0.9f, 0.87f, 0.75f, 1.0f }) } }, RenderArea = new Rect2D { Extent = surfaceCapabilities.CurrentExtent } }; buffers [i].CmdBeginRenderPass(renderPassBeginInfo, SubpassContents.Inline); buffers [i].CmdBindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, descriptorSets, null); buffers [i].CmdBindPipeline(PipelineBindPoint.Graphics, pipeline); buffers [i].CmdBindVertexBuffers(0, new Buffer [] { vertexBuffer }, new DeviceSize [] { 0 }); buffers [i].CmdBindIndexBuffer(indexBuffer, 0, IndexType.Uint16); buffers [i].CmdDrawIndexed(indexLength, 1, 0, 0, 0); buffers [i].CmdEndRenderPass(); buffers [i].End(); } return(buffers); }
private unsafe void InitializeImage(DataBox[] dataBoxes) { var commandBuffer = GraphicsDevice.NativeCopyCommandBuffer; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); if (dataBoxes != null && dataBoxes.Length > 0) { int totalSize = dataBoxes.Length * 4; for (int i = 0; i < dataBoxes.Length; i++) { totalSize += dataBoxes[i].SlicePitch; } SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset); // Upload buffer barrier var bufferMemoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)totalSize); // Image barrier var initialBarrier = new ImageMemoryBarrier(NativeImage, ImageLayout.Undefined, ImageLayout.TransferDestinationOptimal, AccessFlags.None, AccessFlags.TransferWrite, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 1, &initialBarrier); // Copy data boxes to upload buffer var copies = new BufferImageCopy[dataBoxes.Length]; for (int i = 0; i < copies.Length; i++) { var slicePitch = dataBoxes[i].SlicePitch; int arraySlice = i / MipLevels; int mipSlice = i % MipLevels; var mipMapDescription = GetMipMapDescription(mipSlice); SubresourceLayout layout; GraphicsDevice.NativeDevice.GetImageSubresourceLayout(NativeImage, new ImageSubresource(NativeImageAspect, (uint)arraySlice, (uint)mipSlice), out layout); var alignment = ((uploadOffset + 3) & ~3) - uploadOffset; uploadMemory += alignment; uploadOffset += alignment; Utilities.CopyMemory(uploadMemory, dataBoxes[i].DataPointer, slicePitch); // TODO VULKAN: Check if pitches are valid copies[i] = new BufferImageCopy { BufferOffset = (ulong)uploadOffset, ImageSubresource = new ImageSubresourceLayers(ImageAspectFlags.Color, (uint)arraySlice, 1, (uint)mipSlice), BufferRowLength = 0, //(uint)(dataBoxes[i].RowPitch / pixelSize), BufferImageHeight = 0, //(uint)(dataBoxes[i].SlicePitch / dataBoxes[i].RowPitch), ImageOffset = new Offset3D(0, 0, arraySlice), ImageExtent = new Extent3D((uint)mipMapDescription.Width, (uint)mipMapDescription.Height, 1) }; uploadMemory += slicePitch; uploadOffset += slicePitch; } // Copy from upload buffer to image fixed(BufferImageCopy *copiesPointer = &copies[0]) { commandBuffer.CopyBufferToImage(uploadResource, NativeImage, ImageLayout.TransferDestinationOptimal, (uint)copies.Length, copiesPointer); } IsInitialized = true; } // Transition to default layout var imageMemoryBarrier = new ImageMemoryBarrier(NativeImage, dataBoxes == null || dataBoxes.Length == 0 ? ImageLayout.Undefined : ImageLayout.TransferDestinationOptimal, NativeLayout, dataBoxes == null || dataBoxes.Length == 0 ? AccessFlags.None : AccessFlags.TransferWrite, NativeAccessMask, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); commandBuffer.Reset(CommandBufferResetFlags.None); }
private unsafe void CreateBackBuffers() { // Create the texture object var backBufferDescription = new TextureDescription { ArraySize = 1, Dimension = TextureDimension.Texture2D, Height = Description.BackBufferHeight, Width = Description.BackBufferWidth, Depth = 1, Flags = TextureFlags.RenderTarget, Format = Description.BackBufferFormat, MipLevels = 1, MultiSampleLevel = MSAALevel.None, Usage = GraphicsResourceUsage.Default }; backbuffer.InitializeWithoutResources(backBufferDescription); var createInfo = new ImageViewCreateInfo { StructureType = StructureType.ImageViewCreateInfo, SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), Format = backbuffer.NativeFormat, }; // We initialize swapchain images to PresentSource, since we swap them out while in this layout. backbuffer.NativeAccessMask = AccessFlags.MemoryRead; backbuffer.NativeLayout = ImageLayout.PresentSource; var imageMemoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.Undefined, NewLayout = ImageLayout.PresentSource, SourceAccessMask = AccessFlags.None, DestinationAccessMask = AccessFlags.MemoryRead }; var commandBuffer = GraphicsDevice.NativeCopyCommandBuffer; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); var buffers = GraphicsDevice.NativeDevice.GetSwapchainImages(swapChain); swapchainImages = new SwapChainImageInfo[buffers.Length]; for (int i = 0; i < buffers.Length; i++) { // Create image views swapchainImages[i].NativeImage = createInfo.Image = buffers[i]; swapchainImages[i].NativeColorAttachmentView = GraphicsDevice.NativeDevice.CreateImageView(ref createInfo); // Transition to default layout imageMemoryBarrier.Image = buffers[i]; commandBuffer.PipelineBarrier(PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); } // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); commandBuffer.Reset(CommandBufferResetFlags.None); // Get next image currentBufferIndex = GraphicsDevice.NativeDevice.AcquireNextImage(swapChain, ulong.MaxValue, GraphicsDevice.GetNextPresentSemaphore(), Fence.Null); // Apply the first swap chain image to the texture backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView); }
/// <summary> /// Explicitly recreate buffer with given data. Usually called after a <see cref="GraphicsDevice"/> reset. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataPointer"></param> public unsafe void Recreate(IntPtr dataPointer) { var createInfo = new BufferCreateInfo { StructureType = StructureType.BufferCreateInfo, Size = (ulong)bufferDescription.SizeInBytes, Flags = BufferCreateFlags.None, }; createInfo.Usage |= BufferUsageFlags.TransferSource; // We always fill using transfer //if (bufferDescription.Usage != GraphicsResourceUsage.Immutable) createInfo.Usage |= BufferUsageFlags.TransferDestination; if (Usage == GraphicsResourceUsage.Staging) { NativeAccessMask = AccessFlags.HostRead | AccessFlags.HostWrite; NativePipelineStageMask |= PipelineStageFlags.Host; } else { if ((ViewFlags & BufferFlags.VertexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.VertexBuffer; NativeAccessMask |= AccessFlags.VertexAttributeRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.IndexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.IndexBuffer; NativeAccessMask |= AccessFlags.IndexRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.ConstantBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.UniformBuffer; NativeAccessMask |= AccessFlags.UniformRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; } if ((ViewFlags & BufferFlags.ShaderResource) != 0) { createInfo.Usage |= BufferUsageFlags.UniformTexelBuffer; NativeAccessMask |= AccessFlags.ShaderRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; if ((ViewFlags & BufferFlags.UnorderedAccess) != 0) { createInfo.Usage |= BufferUsageFlags.StorageTexelBuffer; NativeAccessMask |= AccessFlags.ShaderWrite; } } } // Create buffer NativeBuffer = GraphicsDevice.NativeDevice.CreateBuffer(ref createInfo); // Allocate memory var memoryProperties = MemoryPropertyFlags.DeviceLocal; if (bufferDescription.Usage == GraphicsResourceUsage.Staging || Usage == GraphicsResourceUsage.Dynamic) { memoryProperties = MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent; } MemoryRequirements memoryRequirements; GraphicsDevice.NativeDevice.GetBufferMemoryRequirements(NativeBuffer, out memoryRequirements); AllocateMemory(memoryProperties, memoryRequirements); if (NativeMemory != DeviceMemory.Null) { GraphicsDevice.NativeDevice.BindBufferMemory(NativeBuffer, NativeMemory, 0); } if (SizeInBytes > 0) { // Begin copy command buffer var commandBufferAllocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = GraphicsDevice.NativeCopyCommandPool, CommandBufferCount = 1, Level = CommandBufferLevel.Primary }; CommandBuffer commandBuffer; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeDevice.AllocateCommandBuffers(ref commandBufferAllocateInfo, &commandBuffer); } var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.OneTimeSubmit }; commandBuffer.Begin(ref beginInfo); // Copy to upload buffer if (dataPointer != IntPtr.Zero) { if (Usage == GraphicsResourceUsage.Dynamic) { var uploadMemory = GraphicsDevice.NativeDevice.MapMemory(NativeMemory, 0, (ulong)SizeInBytes, MemoryMapFlags.None); Utilities.CopyMemory(uploadMemory, dataPointer, SizeInBytes); GraphicsDevice.NativeDevice.UnmapMemory(NativeMemory); } else { var sizeInBytes = bufferDescription.SizeInBytes; SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(sizeInBytes, out uploadResource, out uploadOffset); Utilities.CopyMemory(uploadMemory, dataPointer, sizeInBytes); // Barrier var memoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)sizeInBytes); commandBuffer.PipelineBarrier(PipelineStageFlags.Host, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &memoryBarrier, 0, null); // Copy var bufferCopy = new BufferCopy { SourceOffset = (uint)uploadOffset, DestinationOffset = 0, Size = (uint)sizeInBytes }; commandBuffer.CopyBuffer(uploadResource, NativeBuffer, 1, &bufferCopy); } } else { commandBuffer.FillBuffer(NativeBuffer, 0, (uint)bufferDescription.SizeInBytes, 0); } // Barrier var bufferMemoryBarrier = new BufferMemoryBarrier(NativeBuffer, AccessFlags.TransferWrite, NativeAccessMask); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 0, null); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); //commandBuffer.Reset(CommandBufferResetFlags.None); GraphicsDevice.NativeDevice.FreeCommandBuffers(GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer); } InitializeViews(); } }
private unsafe void CreateBackBuffers() { backbuffer.OnDestroyed(); // Create the texture object var backBufferDescription = new TextureDescription { ArraySize = 1, Dimension = TextureDimension.Texture2D, Height = Description.BackBufferHeight, Width = Description.BackBufferWidth, Depth = 1, Flags = TextureFlags.RenderTarget, Format = Description.BackBufferFormat, MipLevels = 1, MultisampleCount = MultisampleCount.None, Usage = GraphicsResourceUsage.Default }; backbuffer.InitializeWithoutResources(backBufferDescription); var createInfo = new ImageViewCreateInfo { StructureType = StructureType.ImageViewCreateInfo, SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), Format = backbuffer.NativeFormat, ViewType = ImageViewType.Image2D }; // We initialize swapchain images to PresentSource, since we swap them out while in this layout. backbuffer.NativeAccessMask = AccessFlags.MemoryRead; backbuffer.NativeLayout = ImageLayout.PresentSource; var imageMemoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.Undefined, NewLayout = ImageLayout.PresentSource, SourceAccessMask = AccessFlags.None, DestinationAccessMask = AccessFlags.MemoryRead }; var commandBuffer = GraphicsDevice.NativeCopyCommandBuffer; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); var buffers = GraphicsDevice.NativeDevice.GetSwapchainImages(swapChain); swapchainImages = new SwapChainImageInfo[buffers.Length]; for (int i = 0; i < buffers.Length; i++) { // Create image views swapchainImages[i].NativeImage = createInfo.Image = buffers[i]; swapchainImages[i].NativeColorAttachmentView = GraphicsDevice.NativeDevice.CreateImageView(ref createInfo); // Transition to default layout imageMemoryBarrier.Image = buffers[i]; commandBuffer.PipelineBarrier(PipelineStageFlags.AllCommands, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); } // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); commandBuffer.Reset(CommandBufferResetFlags.None); // need to make a fence, but can immediately reset it, as it acts as a dummy var fenceCreateInfo = new FenceCreateInfo { StructureType = StructureType.FenceCreateInfo }; presentFence = GraphicsDevice.NativeDevice.CreateFence(ref fenceCreateInfo); currentBufferIndex = GraphicsDevice.NativeDevice.AcquireNextImage(swapChain, ulong.MaxValue, SharpVulkan.Semaphore.Null, presentFence); fixed(Fence *fences = &presentFence) { GraphicsDevice.NativeDevice.ResetFences(1, fences); } // Apply the first swap chain image to the texture backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView); }
private unsafe void InitializeImage(DataBox[] dataBoxes) { // Begin copy command buffer var commandBufferAllocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = GraphicsDevice.NativeCopyCommandPool, CommandBufferCount = 1, Level = CommandBufferLevel.Primary }; CommandBuffer commandBuffer; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeDevice.AllocateCommandBuffers(ref commandBufferAllocateInfo, &commandBuffer); } var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.OneTimeSubmit }; commandBuffer.Begin(ref beginInfo); if (dataBoxes != null && dataBoxes.Length > 0) { // Buffer-to-image copies need to be aligned to the pixel size and 4 (always a power of 2) var blockSize = Format.IsCompressed() ? NativeFormat.BlockSizeInBytes() : TexturePixelSize; var alignmentMask = (blockSize < 4 ? 4 : blockSize) - 1; int totalSize = dataBoxes.Length * alignmentMask; for (int i = 0; i < dataBoxes.Length; i++) { totalSize += dataBoxes[i].SlicePitch; } SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset); // Upload buffer barrier var bufferMemoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)totalSize); // Image barrier var initialBarrier = new ImageMemoryBarrier(NativeImage, ImageLayout.Undefined, ImageLayout.TransferDestinationOptimal, AccessFlags.None, AccessFlags.TransferWrite, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Host, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 1, &initialBarrier); // Copy data boxes to upload buffer var copies = new BufferImageCopy[dataBoxes.Length]; for (int i = 0; i < copies.Length; i++) { var slicePitch = dataBoxes[i].SlicePitch; int arraySlice = i / MipLevels; int mipSlice = i % MipLevels; var mipMapDescription = GetMipMapDescription(mipSlice); var alignment = ((uploadOffset + alignmentMask) & ~alignmentMask) - uploadOffset; uploadMemory += alignment; uploadOffset += alignment; Utilities.CopyMemory(uploadMemory, dataBoxes[i].DataPointer, slicePitch); // TODO VULKAN: Check if pitches are valid copies[i] = new BufferImageCopy { BufferOffset = (ulong)uploadOffset, ImageSubresource = new ImageSubresourceLayers(ImageAspectFlags.Color, (uint)arraySlice, 1, (uint)mipSlice), BufferRowLength = 0, //(uint)(dataBoxes[i].RowPitch / pixelSize), BufferImageHeight = 0, //(uint)(dataBoxes[i].SlicePitch / dataBoxes[i].RowPitch), ImageOffset = new Offset3D(0, 0, 0), ImageExtent = new Extent3D((uint)mipMapDescription.Width, (uint)mipMapDescription.Height, (uint)mipMapDescription.Depth) }; uploadMemory += slicePitch; uploadOffset += slicePitch; } // Copy from upload buffer to image fixed(BufferImageCopy *copiesPointer = &copies[0]) { commandBuffer.CopyBufferToImage(uploadResource, NativeImage, ImageLayout.TransferDestinationOptimal, (uint)copies.Length, copiesPointer); } IsInitialized = true; } // Transition to default layout var imageMemoryBarrier = new ImageMemoryBarrier(NativeImage, dataBoxes == null || dataBoxes.Length == 0 ? ImageLayout.Undefined : ImageLayout.TransferDestinationOptimal, NativeLayout, dataBoxes == null || dataBoxes.Length == 0 ? AccessFlags.None : AccessFlags.TransferWrite, NativeAccessMask, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); GraphicsDevice.NativeDevice.FreeCommandBuffers(GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer); } }
private void SetImageLayout(Image image, ImageAspectFlags imageAspect, ImageLayout oldLayout, ImageLayout newLayout) { if (setupCommanBuffer == CommandBuffer.Null) { // Create command buffer CommandBuffer setupCommandBuffer; var allocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = commandPool, Level = CommandBufferLevel.Primary, CommandBufferCount = 1, }; device.AllocateCommandBuffers(ref allocateInfo, &setupCommandBuffer); setupCommanBuffer = setupCommandBuffer; // Begin command buffer var inheritanceInfo = new CommandBufferInheritanceInfo { StructureType = StructureType.CommandBufferInheritanceInfo }; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, InheritanceInfo = new IntPtr(&inheritanceInfo) }; setupCommanBuffer.Begin(ref beginInfo); } var imageMemoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, OldLayout = oldLayout, NewLayout = newLayout, Image = image, SubresourceRange = new ImageSubresourceRange(imageAspect, 0, 1, 0, 1) }; switch (newLayout) { case ImageLayout.TransferDestinationOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.TransferRead; break; case ImageLayout.ColorAttachmentOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.ColorAttachmentWrite; break; case ImageLayout.DepthStencilAttachmentOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.DepthStencilAttachmentWrite; break; case ImageLayout.ShaderReadOnlyOptimal: imageMemoryBarrier.DestinationAccessMask = AccessFlags.ShaderRead | AccessFlags.InputAttachmentRead; break; } var sourceStages = PipelineStageFlags.TopOfPipe; var destinationStages = PipelineStageFlags.TopOfPipe; setupCommanBuffer.PipelineBarrier(sourceStages, destinationStages, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); }
protected unsafe virtual void Draw() { var semaphoreCreateInfo = new SemaphoreCreateInfo { StructureType = StructureType.SemaphoreCreateInfo }; var presentCompleteSemaphore = device.CreateSemaphore(ref semaphoreCreateInfo); try { // Get the index of the next available swapchain image currentBackBufferIndex = device.AcquireNextImage(this.swapchain, ulong.MaxValue, presentCompleteSemaphore, Fence.Null); } catch (SharpVulkanException e) when (e.Result == Result.ErrorOutOfDate) { // TODO: Handle resize and retry draw throw new NotImplementedException(); } // Record drawing command buffer var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); DrawInternal(); commandBuffer.End(); // Submit var drawCommandBuffer = commandBuffer; var pipelineStageFlags = PipelineStageFlags.BottomOfPipe; var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, WaitSemaphoreCount = 1, WaitSemaphores = new IntPtr(&presentCompleteSemaphore), WaitDstStageMask = new IntPtr(&pipelineStageFlags), CommandBufferCount = 1, CommandBuffers = new IntPtr(&drawCommandBuffer), }; queue.Submit(1, &submitInfo, Fence.Null); // Present var swapchain = this.swapchain; var currentBackBufferIndexCopy = currentBackBufferIndex; var presentInfo = new PresentInfo { StructureType = StructureType.PresentInfo, SwapchainCount = 1, Swapchains = new IntPtr(&swapchain), ImageIndices = new IntPtr(¤tBackBufferIndexCopy) }; queue.Present(ref presentInfo); // Wait queue.WaitIdle(); device.ResetDescriptorPool(descriptorPool, DescriptorPoolResetFlags.None); // Cleanup device.DestroySemaphore(presentCompleteSemaphore); }
protected virtual unsafe void Draw() { var semaphoreCreateInfo = new SemaphoreCreateInfo { StructureType = StructureType.SemaphoreCreateInfo }; var presentCompleteSemaphore = device.CreateSemaphore(ref semaphoreCreateInfo); try { // Get the index of the next available swapchain image currentBackBufferIndex = device.AcquireNextImage(this.swapchain, ulong.MaxValue, presentCompleteSemaphore, Fence.Null); } catch (SharpVulkanException e) when(e.Result == Result.ErrorOutOfDate) { // TODO: Handle resize and retry draw throw new NotImplementedException(); } // Record drawing command buffer var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); DrawInternal(); commandBuffer.End(); // Submit var drawCommandBuffer = commandBuffer; var pipelineStageFlags = PipelineStageFlags.BottomOfPipe; var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, WaitSemaphoreCount = 1, WaitSemaphores = new IntPtr(&presentCompleteSemaphore), WaitDstStageMask = new IntPtr(&pipelineStageFlags), CommandBufferCount = 1, CommandBuffers = new IntPtr(&drawCommandBuffer), }; queue.Submit(1, &submitInfo, Fence.Null); // Present var swapchain = this.swapchain; var currentBackBufferIndexCopy = currentBackBufferIndex; var presentInfo = new PresentInfo { StructureType = StructureType.PresentInfo, SwapchainCount = 1, Swapchains = new IntPtr(&swapchain), ImageIndices = new IntPtr(¤tBackBufferIndexCopy) }; queue.Present(ref presentInfo); // Wait queue.WaitIdle(); device.ResetDescriptorPool(descriptorPool, DescriptorPoolResetFlags.None); // Cleanup device.DestroySemaphore(presentCompleteSemaphore); }
private unsafe void InitializeImage(DataBox[] dataBoxes) { var commandBuffer = GraphicsDevice.NativeCopyCommandBuffer; var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo }; commandBuffer.Begin(ref beginInfo); if (dataBoxes != null && dataBoxes.Length > 0) { // Buffer-to-image copies need to be aligned to the pixel size and 4 (always a power of 2) var blockSize = Format.IsCompressed() ? NativeFormat.BlockSizeInBytes() : TexturePixelSize; var alignmentMask = (blockSize < 4 ? 4 : blockSize) - 1; int totalSize = dataBoxes.Length * alignmentMask; for (int i = 0; i < dataBoxes.Length; i++) { totalSize += dataBoxes[i].SlicePitch; } SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset); // Upload buffer barrier var bufferMemoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)totalSize); // Image barrier var initialBarrier = new ImageMemoryBarrier(NativeImage, ImageLayout.Undefined, ImageLayout.TransferDestinationOptimal, AccessFlags.None, AccessFlags.TransferWrite, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 1, &initialBarrier); // Copy data boxes to upload buffer var copies = new BufferImageCopy[dataBoxes.Length]; for (int i = 0; i < copies.Length; i++) { var slicePitch = dataBoxes[i].SlicePitch; int arraySlice = i / MipLevels; int mipSlice = i % MipLevels; var mipMapDescription = GetMipMapDescription(mipSlice); SubresourceLayout layout; GraphicsDevice.NativeDevice.GetImageSubresourceLayout(NativeImage, new ImageSubresource(NativeImageAspect, (uint)arraySlice, (uint)mipSlice), out layout); var alignment = ((uploadOffset + alignmentMask) & ~alignmentMask) - uploadOffset; uploadMemory += alignment; uploadOffset += alignment; Utilities.CopyMemory(uploadMemory, dataBoxes[i].DataPointer, slicePitch); // TODO VULKAN: Check if pitches are valid copies[i] = new BufferImageCopy { BufferOffset = (ulong)uploadOffset, ImageSubresource = new ImageSubresourceLayers(ImageAspectFlags.Color, (uint)arraySlice, 1, (uint)mipSlice), BufferRowLength = 0, //(uint)(dataBoxes[i].RowPitch / pixelSize), BufferImageHeight = 0, //(uint)(dataBoxes[i].SlicePitch / dataBoxes[i].RowPitch), ImageOffset = new Offset3D(0, 0, arraySlice), ImageExtent = new Extent3D((uint)mipMapDescription.Width, (uint)mipMapDescription.Height, 1) }; uploadMemory += slicePitch; uploadOffset += slicePitch; } // Copy from upload buffer to image fixed (BufferImageCopy* copiesPointer = &copies[0]) { commandBuffer.CopyBufferToImage(uploadResource, NativeImage, ImageLayout.TransferDestinationOptimal, (uint)copies.Length, copiesPointer); } IsInitialized = true; } // Transition to default layout var imageMemoryBarrier = new ImageMemoryBarrier(NativeImage, dataBoxes == null || dataBoxes.Length == 0 ? ImageLayout.Undefined : ImageLayout.TransferDestinationOptimal, NativeLayout, dataBoxes == null || dataBoxes.Length == 0 ? AccessFlags.None : AccessFlags.TransferWrite, NativeAccessMask, new ImageSubresourceRange(NativeImageAspect)); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); commandBuffer.Reset(CommandBufferResetFlags.None); } }
void RecordCommandBuffers() { var graphics_commandd_buffer_begin_info = new CommandBufferBeginInfo { sType = StructureType.CommandBufferBeginInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = CommandBufferUsageFlagBits.SimultaneousUseBit, // VkCommandBufferUsageFlagBits flags pInheritanceInfo = (CommandBufferInheritanceInfo *)0 // const VkCommandBufferInheritanceInfo *pInheritanceInfo }; var image_subresource_range = new ImageSubresourceRange { aspectMask = ImageAspectFlagBits.ColorBit, // VkImageAspectFlagBits aspectMask baseMipLevel = 0, // uint32_t baseMipLevel layerCount = 1, // uint32_t levelCount baseArrayLayer = 0, // uint32_t baseArrayLayer levelCount = 1 // uint32_t layerCount }; var clear_value = new ClearValue { color = new ClearColorValue(1.0f, 0.8f, 0.4f, 0.0f), // VkClearColorValue color }; ImageParameters[] swap_chain_images = GetSwapChain.Images; for (int i = 0; i < Vulkan.GraphicsCommandBuffers.Length; ++i) { vk.BeginCommandBuffer(Vulkan.GraphicsCommandBuffers[i], ref graphics_commandd_buffer_begin_info).CheckError(); if (GetPresentQueue.Handle != GetGraphicsQueue.Handle) { var barrier_from_present_to_draw = new ImageMemoryBarrier { sType = StructureType.ImageMemoryBarrier, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext sourceAccessMask = AccessFlagBits.MemoryReadBit, // VkAccessFlagBits srcAccessMask destinationAccessMask = AccessFlagBits.ColorAttachmentWriteBit, // VkAccessFlagBits dstAccessMask oldLayout = ImageLayout.Undefined, // VkImageLayout oldLayout newLayout = ImageLayout.PresentSourceKhr, // VkImageLayout newLayout sourceQueueFamilyIndex = GetPresentQueue.FamilyIndex, // uint32_t srcQueueFamilyIndex destinationQueueFamilyIndex = GetGraphicsQueue.FamilyIndex, // uint32_t dstQueueFamilyIndex image = swap_chain_images[i].Handle, // VkImage image subresourceRange = image_subresource_range // VkImageSubresourceRange subresourceRange }; vk.CmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], PipelineStageFlagBits.ColorAttachmentOutputBit, PipelineStageFlagBits.ColorAttachmentOutputBit, (DependencyFlagBits)0, 0, (MemoryBarrier *)0, 0, (BufferMemoryBarrier *)0, 1, &barrier_from_present_to_draw); } var render_pass_begin_info = new RenderPassBeginInfo { sType = StructureType.RenderPassBeginInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext renderPass = Vulkan.RenderPass, // VkRenderPass renderPass framebuffer = Vulkan.Framebuffers[i], // VkFramebuffer framebuffer renderArea = new Rect2D { // VkRect2D renderArea offset = new Offset2D { // VkOffset2D offset x = 0, // int32_t x y = 0 // int32_t y }, extent = new Extent2D { // VkExtent2D extent width = 300, // int32_t width height = 300, // int32_t height } }, clearValueCount = 1, // uint32_t clearValueCount pClearValues = &clear_value // const VkClearValue *pClearValues }; vk.CmdBeginRenderPass(Vulkan.GraphicsCommandBuffers[i], ref render_pass_begin_info, SubpassContents.Inline); vk.CmdBindPipeline(Vulkan.GraphicsCommandBuffers[i], PipelineBindPoint.Graphics, Vulkan.GraphicsPipeline); vk.CmdDraw(Vulkan.GraphicsCommandBuffers[i], 3, 1, 0, 0); vk.CmdEndRenderPass(Vulkan.GraphicsCommandBuffers[i]); if (GetGraphicsQueue.Handle != GetPresentQueue.Handle) { var barrier_from_draw_to_present = new ImageMemoryBarrier { sType = StructureType.ImageMemoryBarrier, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext sourceAccessMask = AccessFlagBits.ColorAttachmentWriteBit, // VkAccessFlagBits srcAccessMask destinationAccessMask = AccessFlagBits.MemoryReadBit, // VkAccessFlagBits dstAccessMask oldLayout = ImageLayout.PresentSourceKhr, // VkImageLayout oldLayout newLayout = ImageLayout.PresentSourceKhr, // VkImageLayout newLayout sourceQueueFamilyIndex = GetGraphicsQueue.FamilyIndex, // uint32_t srcQueueFamilyIndex destinationQueueFamilyIndex = GetPresentQueue.FamilyIndex, // uint32_t dstQueueFamilyIndex image = swap_chain_images[i].Handle, // VkImage image subresourceRange = image_subresource_range // VkImageSubresourceRange subresourceRange }; vk.CmdPipelineBarrier( Vulkan.GraphicsCommandBuffers[i], PipelineStageFlagBits.ColorAttachmentOutputBit, PipelineStageFlagBits.BottomOfPipeBit, (DependencyFlagBits)0, 0, (MemoryBarrier *)0, 0, (BufferMemoryBarrier *)0, 1, &barrier_from_draw_to_present); } vk.EndCommandBuffer(Vulkan.GraphicsCommandBuffers[i]).CheckError(); } }
ImageData LoadTexture(string filename, Queue queue, CommandPool cmdPool) { // var bmp = new Bitmap(filename); var bitmapFormat = System.Drawing.Imaging.PixelFormat.Format32bppArgb; var rect = new Rectangle(0, 0, bmp.Width, bmp.Height); var bitmapData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmapFormat); // uint imageWidth = (uint)bmp.Width; uint imageHeight = (uint)bmp.Height; var imageData = new ImageData(); imageData.Width = imageWidth; imageData.Height = imageHeight; imageData.Image = CreateTextureImage(Format.B8g8r8a8Unorm, imageWidth, imageHeight); imageData.Memory = BindImage(imageData.Image); imageData.View = CreateImageView(imageData.Image, Format.B8g8r8a8Unorm); imageData.Sampler = CreateSampler(); var memRequirements = device.GetImageMemoryRequirements(imageData.Image); var imageBuffer = CreateBuffer(memRequirements.Size, BufferUsageFlags.TransferSrc | BufferUsageFlags.TransferDst); var memoryIndex = FindMemoryIndex(MemoryPropertyFlags.HostVisible); var memAlloc = new MemoryAllocateInfo(memRequirements.Size, memoryIndex); var bufferMemory = BindBuffer(imageBuffer, memAlloc); CopyBitmapToBuffer(bitmapData.Scan0, (int)(imageWidth * imageHeight * 4), bufferMemory, memRequirements); // var cmdBuffers = AllocateCommandBuffers(cmdPool, 1); var cmdBuffer = cmdBuffers[0]; var beginInfo = new CommandBufferBeginInfo(); cmdBuffer.Begin(beginInfo); PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.Preinitialized, ImageLayout.TransferDstOptimal, AccessFlags.HostWrite, AccessFlags.TransferWrite); CopyBufferToImage(cmdBuffer, imageData, imageBuffer); PipelineBarrierSetLayout(cmdBuffer, imageData.Image, ImageLayout.TransferDstOptimal, ImageLayout.ShaderReadOnlyOptimal, AccessFlags.TransferWrite, AccessFlags.ShaderRead); // wait... why does this work? device.DestroyBuffer(imageBuffer); device.FreeMemory(bufferMemory); cmdBuffer.End(); var submitInfo = new SubmitInfo(null, null, new[] { cmdBuffer }, null); queue.Submit(new[] { submitInfo }); submitInfo.Dispose(); queue.WaitIdle(); device.FreeCommandBuffers(cmdPool, new[] { cmdBuffer }); // //CopyBufferToImage(queue, cmdPool, imageData, imageBuffer); // bmp.UnlockBits(bitmapData); bmp.Dispose(); // return(imageData); }
/// <summary> /// Explicitly recreate buffer with given data. Usually called after a <see cref="GraphicsDevice"/> reset. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataPointer"></param> public unsafe void Recreate(IntPtr dataPointer) { var createInfo = new BufferCreateInfo { StructureType = StructureType.BufferCreateInfo, Size = (ulong)bufferDescription.SizeInBytes, Flags = BufferCreateFlags.None, }; createInfo.Usage |= BufferUsageFlags.TransferSource; // We always fill using transfer //if (bufferDescription.Usage != GraphicsResourceUsage.Immutable) createInfo.Usage |= BufferUsageFlags.TransferDestination; if ((ViewFlags & BufferFlags.VertexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.VertexBuffer; NativeAccessMask |= AccessFlags.VertexAttributeRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.IndexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.IndexBuffer; NativeAccessMask |= AccessFlags.IndexRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.ConstantBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.UniformBuffer; NativeAccessMask |= AccessFlags.UniformRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; } if ((ViewFlags & BufferFlags.ShaderResource) != 0) { createInfo.Usage |= BufferUsageFlags.UniformTexelBuffer; NativeAccessMask |= AccessFlags.ShaderRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; if ((ViewFlags & BufferFlags.UnorderedAccess) != 0) { createInfo.Usage |= BufferUsageFlags.StorageTexelBuffer; NativeAccessMask |= AccessFlags.ShaderWrite; } } // Create buffer NativeBuffer = GraphicsDevice.NativeDevice.CreateBuffer(ref createInfo); // Allocate memory var memoryProperties = MemoryPropertyFlags.DeviceLocal; if (bufferDescription.Usage == GraphicsResourceUsage.Staging) { throw new NotImplementedException(); } else if (Usage == GraphicsResourceUsage.Dynamic) { memoryProperties = MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent; } MemoryRequirements memoryRequirements; GraphicsDevice.NativeDevice.GetBufferMemoryRequirements(NativeBuffer, out memoryRequirements); AllocateMemory(memoryProperties, memoryRequirements); if (NativeMemory != DeviceMemory.Null) { GraphicsDevice.NativeDevice.BindBufferMemory(NativeBuffer, NativeMemory, 0); } if (SizeInBytes > 0) { // Begin copy command buffer var commandBufferAllocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = GraphicsDevice.NativeCopyCommandPool, CommandBufferCount = 1, Level = CommandBufferLevel.Primary }; CommandBuffer commandBuffer; GraphicsDevice.NativeDevice.AllocateCommandBuffers(ref commandBufferAllocateInfo, &commandBuffer); var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.OneTimeSubmit }; commandBuffer.Begin(ref beginInfo); // Copy to upload buffer if (dataPointer != IntPtr.Zero) { if (Usage == GraphicsResourceUsage.Dynamic) { var uploadMemory = GraphicsDevice.NativeDevice.MapMemory(NativeMemory, 0, (ulong)SizeInBytes, MemoryMapFlags.None); Utilities.CopyMemory(uploadMemory, dataPointer, SizeInBytes); GraphicsDevice.NativeDevice.UnmapMemory(NativeMemory); } else { var sizeInBytes = bufferDescription.SizeInBytes; SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(sizeInBytes, out uploadResource, out uploadOffset); Utilities.CopyMemory(uploadMemory, dataPointer, sizeInBytes); // Barrier var memoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)sizeInBytes); commandBuffer.PipelineBarrier(PipelineStageFlags.Host, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &memoryBarrier, 0, null); // Copy var bufferCopy = new BufferCopy { SourceOffset = (uint)uploadOffset, DestinationOffset = 0, Size = (uint)sizeInBytes }; commandBuffer.CopyBuffer(uploadResource, NativeBuffer, 1, &bufferCopy); } } else { commandBuffer.FillBuffer(NativeBuffer, 0, (uint)bufferDescription.SizeInBytes, 0); } // Barrier var bufferMemoryBarrier = new BufferMemoryBarrier(NativeBuffer, AccessFlags.TransferWrite, NativeAccessMask); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 0, null); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); //commandBuffer.Reset(CommandBufferResetFlags.None); GraphicsDevice.NativeDevice.FreeCommandBuffers(GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer); } InitializeViews(); } }
internal static unsafe extern Result vkBeginCommandBuffer(CommandBuffer commandBuffer, CommandBufferBeginInfo* beginInfo);