Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan Bitmap #9

Open
Gergilcan opened this issue Jun 19, 2016 · 2 comments
Open

Vulkan Bitmap #9

Gergilcan opened this issue Jun 19, 2016 · 2 comments

Comments

@Gergilcan
Copy link

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);
}
@jwollen
Copy link
Owner

jwollen commented Jun 20, 2016

Hi!

How did you try to read back the image?

The best approach would be to copy it to a buffer and map that buffer. You will need to wait for the copy to finish using a fence. See vkCmdCopyImageToBuffer, vkWaitForFences, vkMapMemory.

Your best bet is to look for a sample that demonstrated taking a screenshot.

@Gergilcan
Copy link
Author

Gergilcan commented Jun 20, 2016

Hi, I understand but I was not able to find any sample that implements this screenshot approach, do you know where can i get it? thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants