0
$\begingroup$

Using Vulkan, I am reading from an image to a vector of unsigned char. It works great.

vkCmdTraceRaysKHR(
    screenshotCmdBuffer,
    &shaderBindingTables.raygen.stridedDeviceAddressRegion,
    &shaderBindingTables.miss.stridedDeviceAddressRegion,
    &shaderBindingTables.hit.stridedDeviceAddressRegion,
    &emptySbtEntry,
    size_x,
    size_y,
    1);

vks::tools::setImageLayout(
    screenshotCmdBuffer,
    screenshotStorageImage.image,
    VK_IMAGE_LAYOUT_GENERAL,
    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    subresourceRange);

VkBufferImageCopy copyRegion{};
copyRegion.bufferOffset = 0;
copyRegion.bufferRowLength = 0;
copyRegion.bufferImageHeight = 0;

copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyRegion.imageSubresource.mipLevel = 0;
copyRegion.imageSubresource.baseArrayLayer = 0;
copyRegion.imageSubresource.layerCount = 1;

copyRegion.imageOffset = { 0, 0, 0 };
copyRegion.imageExtent.width = size_x;
copyRegion.imageExtent.height = size_y;
copyRegion.imageExtent.depth = 1;

vkCmdCopyImageToBuffer(screenshotCmdBuffer, screenshotStorageImage.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, screenshotStagingBuffer.buffer, 1, &copyRegion);

VkBufferMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
barrier.buffer = screenshotStagingBuffer.buffer;
barrier.size = screenshotStagingBuffer.size;

vkCmdPipelineBarrier(
    screenshotCmdBuffer,
    VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
    0,
    0, nullptr,
    1, &barrier,
    0, nullptr
);

vulkanDevice->flushCommandBuffer(screenshotCmdBuffer, queue);

memcpy(&fbpixels[0], screenshotStagingBuffer.mapped, size);

How would I go about writing from a vector of unsigned char to an image?

This is a code that I've been trying, but it does not work:

memcpy(screenshotStagingBuffer.mapped, &uc_output_data[0], size);

VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };

vks::tools::setImageLayout(
    screenshotCmdBuffer,
    screenshotStorageImage.image,
    VK_IMAGE_LAYOUT_GENERAL,
    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    subresourceRange);

VkBufferImageCopy copyRegion{};
copyRegion.bufferOffset = 0;
copyRegion.bufferRowLength = 0;
copyRegion.bufferImageHeight = 0;

copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyRegion.imageSubresource.mipLevel = 0;
copyRegion.imageSubresource.baseArrayLayer = 0;
copyRegion.imageSubresource.layerCount = 1;

copyRegion.imageOffset = { 0, 0, 0 };
copyRegion.imageExtent.width = size_x;
copyRegion.imageExtent.height = size_y;
copyRegion.imageExtent.depth = 1;

vkCmdCopyBufferToImage(
    screenshotCmdBuffer,
    screenshotStagingBuffer.buffer,
    screenshotStorageImage.image,
    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    1,
    &copyRegion);

VkBufferMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.buffer = screenshotStagingBuffer.buffer;
barrier.size = screenshotStagingBuffer.size;

vkCmdPipelineBarrier(
    screenshotCmdBuffer,
    VK_PIPELINE_STAGE_HOST_BIT,
    VK_PIPELINE_STAGE_TRANSFER_BIT,
    0,
    0, nullptr,
    1, &barrier,
    0, nullptr);

vulkanDevice->flushCommandBuffer(screenshotCmdBuffer, queue);

Should I be using an image memory barrier instead of a buffer memory barrier?

The validation layers says that:

ERROR: [1458672316][VUID-VkSamplerCreateInfo-anisotropyEnable-01070] : Validation Error: [ VUID-VkSamplerCreateInfo-anisotropyEnable-01070 ] | MessageID = 0x56f192bc | vkCreateSampler(): Anisotropic sampling feature is not enabled, pCreateInfo->anisotropyEnable must be VK_FALSE. The Vulkan spec states: If the samplerAnisotropy feature is not enabled, anisotropyEnable must be VK_FALSE (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)

ERROR: [1458672316][VUID-VkSamplerCreateInfo-anisotropyEnable-01070] : Validation Error: [ VUID-VkSamplerCreateInfo-anisotropyEnable-01070 ] | MessageID = 0x56f192bc | vkCreateSampler(): Anisotropic sampling feature is not enabled, pCreateInfo->anisotropyEnable must be VK_FALSE. The Vulkan spec states: If the samplerAnisotropy feature is not enabled, anisotropyEnable must be VK_FALSE (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkSamplerCreateInfo-anisotropyEnable-01070)

ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)

ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)

ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)

ERROR: [706474367][VUID-VkShaderModuleCreateInfo-pCode-01379] : Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-01379 ] | MessageID = 0x2a1bf17f | SPIR-V module not valid: Invalid SPIR-V binary version 1.5 for target environment SPIR-V 1.4 (under Vulkan 1.1 semantics). The Vulkan spec states: If pCode is a pointer to GLSL code, it must be valid GLSL code written to the GL_KHR_vulkan_glsl GLSL extension specification (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-01379)

ERROR: [1132206547][VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849] : Validation Error: [ VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 ] | MessageID = 0x437c19d3 | vkCreateRayTracingPipelinesKHR(): pCreateInfos[0] After specialization was applied, VkShaderModule 0x5011aa0000000066[] does not contain valid spirv for stage VK_SHADER_STAGE_RAYGEN_BIT_KHR. The Vulkan spec states: If a shader module identifier is not specified, the shader code used by the pipeline must be valid as described by the Khronos SPIR-V Specification after applying the specializations provided in pSpecializationInfo, if any, and then converting all specialization constants into fixed constants (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849)

ERROR: [-507995293][VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358] : Validation Error: [ VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358 ] Object 0: handle = 0x612f93000000004e, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0xe1b89b63 | vkCmdBindDescriptorSets(): descriptorSet #1 being bound is not compatible with overlapping descriptorSetLayout at index 1 of VkPipelineLayout 0x5dbcf90000000065[] due to: Binding 0 for VkDescriptorSetLayout 0x9f58380000000064[] from pipeline layout has stageFlags VK_SHADER_STAGE_RAYGEN_BIT_KHR|VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR but binding 0 for VkDescriptorSetLayout 0x73a850000000004d[], which is bound, has stageFlags VK_SHADER_STAGE_FRAGMENT_BIT. The Vulkan spec states: Each element of pDescriptorSets must have been allocated with a VkDescriptorSetLayout that matches (is the same as, or identically defined as) the VkDescriptorSetLayout at set n in layout, where n is the sum of firstSet and the index into pDescriptorSets (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358)

ERROR: [387543851][VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189] : Validation Error: [ VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189 ] Object 0: handle = 0x1f51f40a150, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x421a0f0000000074, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x1719732b | vkCmdCopyImageToBuffer: Cannot use VkImage 0x421a0f0000000074[] (layer=0 mip=0) with specific layout VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL that doesn't match the previous known layout VK_IMAGE_LAYOUT_GENERAL. The Vulkan spec states: srcImageLayout must specify the layout of the image subresources of srcImage specified in pRegions at the time this command is executed on a VkDevice (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdCopyImageToBuffer-srcImageLayout-00189)

ERROR: [455308668][VUID-vkCmdPipelineBarrier-commandBuffer-parameter] : Validation Error: [ VUID-vkCmdPipelineBarrier-commandBuffer-parameter ] Object 0: handle = 0x1f50c70d820, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x1b23757c | vkCmdPipelineBarrier(): Invalid VkCommandBuffer Object 0x1f51f40a150. The Vulkan spec states: commandBuffer must be a valid VkCommandBuffer handle (https://vulkan.lunarg.com/doc/view/1.3.261.1/windows/1.3-extensions/vkspec.html#VUID-vkCmdPipelineBarrier-commandBuffer-parameter)

Any help is much appreciated.

$\endgroup$
3
  • 2
    $\begingroup$ Judging by the validation layer output, you have quite a bit of clean up work to do. It's hard to see from that, but I believe the very last layer message relates to your problem, there seems to be something off with your command buffer, though with the source code given I have no way to say what may be not working. If you add code to set debug names with vkSetDebugUtilsObjectNameEXT, it would be a bit easier to interpret the layer messages, as they add those names. Perhaps also have a look with RenderDoc, see if that gives you more information. $\endgroup$
    – Tare
    Feb 12 at 7:46
  • $\begingroup$ Hi @Tare, thank you for your input. Do you know, should I be using an image memory barrier instead of a buffer memory barrier? $\endgroup$ Feb 12 at 15:59
  • 1
    $\begingroup$ Sorry, but I don't know if it is "illegal" - but if it were, I'd expect the validation layers to throw an error. You could try to do it without a memory barrier and put a few "vkDeviceWaitIdle` before attempting to copy. In one of my projects I use vkCmdCopyBufferToImage, but I don't flush like you do. Instead, I use the beginSingleTimeCommands technique from the tutorial, see: vulkan-tutorial.com/Texture_mapping/Images (i.e. submit to a queue and then wait for the queue to finish with vkQueueWaitIdle). Inefficient to wait this way, but perhaps try for testing $\endgroup$
    – Tare
    Feb 12 at 20:07

1 Answer 1

0
$\begingroup$

I was not creating a command buffer properly. I added one line pertaining to the screenshot command buffer, and it all works now, using an image memory barrier:

if (num_cams_wide == 1)
{
    // This is the line that I added to make it all work...
    VkCommandBuffer screenshotCmdBuffer = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);

    memcpy(screenshotStagingBuffer.mapped, &uc_output_data[0], size);

    VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };

    vks::tools::setImageLayout(
        screenshotCmdBuffer,
        screenshotStorageImage.image,
        VK_IMAGE_LAYOUT_UNDEFINED,
        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
        subresourceRange);

    VkBufferImageCopy copyRegion{};
    copyRegion.bufferOffset = 0;
    copyRegion.bufferRowLength = 0;
    copyRegion.bufferImageHeight = 0;
    copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    copyRegion.imageSubresource.mipLevel = 0;
    copyRegion.imageSubresource.baseArrayLayer = 0;
    copyRegion.imageSubresource.layerCount = 1;
    copyRegion.imageOffset = { 0, 0, 0 };
    copyRegion.imageExtent.width = size_x;
    copyRegion.imageExtent.height = size_y;
    copyRegion.imageExtent.depth = 1;

    VkImageMemoryBarrier imageMemoryBarrier;
    imageMemoryBarrier.image = screenshotStorageImage.image;
    imageMemoryBarrier.subresourceRange = subresourceRange;
    imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_READ_BIT;
    imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
    imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;

    vkCmdCopyBufferToImage(
        screenshotCmdBuffer,
        screenshotStagingBuffer.buffer,
        screenshotStorageImage.image,
        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
        1,
        &copyRegion);

    vkCmdPipelineBarrier(
        screenshotCmdBuffer,
        VK_PIPELINE_STAGE_HOST_BIT,
        VK_PIPELINE_STAGE_TRANSFER_BIT,
        0,
        0, nullptr,
        0, nullptr,
        1, &imageMemoryBarrier);

    vulkanDevice->flushCommandBuffer(screenshotCmdBuffer, queue);
}

The results are a denoised on screen image:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.