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$ Commented Feb 12, 2024 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$ Commented Feb 12, 2024 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$ Commented Feb 12, 2024 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$
1
  • $\begingroup$ Great that you could find a solution. Please mark your answer as accepted $\endgroup$ Commented Jul 15, 2024 at 10:51

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.