Skip to content
This repository was archived by the owner on Mar 21, 2025. It is now read-only.
This repository was archived by the owner on Mar 21, 2025. It is now read-only.

Vulkan Bitmap #9

@Gergilcan

Description

@Gergilcan

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(&currentBackBufferIndexCopy)
    };
    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, &copy);

    // 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);
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions