This repository was archived by the owner on Mar 21, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
This repository was archived by the owner on Mar 21, 2025. It is now read-only.
Vulkan Bitmap #9
Copy link
Copy link
Open
Labels
Description
Hi, I want to obtain a Bitmap from Vulkan, I have created a renderless implementation of the Vulkan rendering and I want to obtain an Image to display the results in the screen, but I'm unable to obtain the image byte data. My Draw function is the following one:
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 void DrawInternal()
{
// Update descriptors
var descriptorSets = stackalloc DescriptorSet[2];
var setLayouts = stackalloc DescriptorSetLayout[2];
setLayouts[0] = setLayouts[1] = descriptorSetLayout;
var allocateInfo = new DescriptorSetAllocateInfo
{
StructureType = StructureType.DescriptorSetAllocateInfo,
DescriptorPool = descriptorPool,
DescriptorSetCount = 2,
SetLayouts = new IntPtr(setLayouts),
};
device.AllocateDescriptorSets(ref allocateInfo, descriptorSets);
var bufferInfo = new DescriptorBufferInfo
{
Buffer = uniformBuffer,
Range = Vulkan.WholeSize
};
var write = new WriteDescriptorSet
{
StructureType = StructureType.WriteDescriptorSet,
DescriptorCount = 1,
DestinationSet = descriptorSets[0],
DestinationBinding = 0,
DescriptorType = DescriptorType.UniformBuffer,
BufferInfo = new IntPtr(&bufferInfo)
};
var copy = new CopyDescriptorSet
{
StructureType = StructureType.CopyDescriptorSet,
DescriptorCount = 1,
SourceBinding = 0,
DestinationBinding = 0,
SourceSet = descriptorSets[0],
DestinationSet = descriptorSets[1]
};
device.UpdateDescriptorSets(1, &write, 0, null);
device.UpdateDescriptorSets(0, null, 1, ©);
// Post-present transition
var memoryBarrier = new ImageMemoryBarrier
{
StructureType = StructureType.ImageMemoryBarrier,
Image = backBuffers[currentBackBufferIndex],
SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1),
OldLayout = ImageLayout.PresentSource,
NewLayout = ImageLayout.ColorAttachmentOptimal,
SourceAccessMask = AccessFlags.MemoryRead,
DestinationAccessMask = AccessFlags.ColorAttachmentWrite
};
commandBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier);
// Clear render target
var clearRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1);
commandBuffer.ClearColorImage(backBuffers[currentBackBufferIndex], ImageLayout.TransferDestinationOptimal, new RawColor4(0, 0, 0, 1), 1, &clearRange);
// Begin render pass
var renderPassBeginInfo = new RenderPassBeginInfo
{
StructureType = StructureType.RenderPassBeginInfo,
RenderPass = renderPass,
Framebuffer = framebuffers[currentBackBufferIndex],
RenderArea = new Rect2D(0, 0, (uint)ActualWidth, (uint)ActualHeight),
};
commandBuffer.BeginRenderPass(ref renderPassBeginInfo, SubpassContents.Inline);
// Bind pipeline
commandBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline);
// Bind descriptor sets
commandBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, 1, descriptorSets + 1, 0, null);
// Set viewport and scissor
var viewport = new Viewport(0, 0, (float)ActualWidth, (float)ActualHeight);
commandBuffer.SetViewport(0, 1, &viewport);
var scissor = new Rect2D(0, 0, (uint)ActualWidth, (uint)ActualHeight);
commandBuffer.SetScissor(0, 1, &scissor);
// Bind vertex buffer
var vertexBufferCopy = vertexBuffer;
ulong offset = 0;
commandBuffer.BindVertexBuffers(0, 1, &vertexBufferCopy, &offset);
// Draw vertices
commandBuffer.Draw(3, 1, 0, 0);
// End render pass
commandBuffer.EndRenderPass();
// Pre-present transition
memoryBarrier = new ImageMemoryBarrier
{
StructureType = StructureType.ImageMemoryBarrier,
Image = backBuffers[currentBackBufferIndex],
SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1),
OldLayout = ImageLayout.ColorAttachmentOptimal,
NewLayout = ImageLayout.PresentSource,
SourceAccessMask = AccessFlags.ColorAttachmentWrite,
DestinationAccessMask = AccessFlags.MemoryRead
};
commandBuffer.PipelineBarrier(PipelineStageFlags.AllCommands, PipelineStageFlags.BottomOfPipe, DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier);
}