Save vkImage generated in Compute Shader to file

Hi

Beginner in Vulkan and also graphics programming as well a cpp, I could successfully render a very nice looking Galaxy skymap using a simple 2 stage Graphics pipeline composed of a vertex and a fragment stage (using VK_PRIMITIVE_TOPOLOGY_POINT_LIST). I followed many famous tutorials and also various recipes from the 3D Graphics Rendering Cookbook.

This Skymap is obtained not from a photography but from ~ 2 billions data points representing position,magnitude and color of each star. These data points are first aggregated in healpixes on CPU ( a famous tesselation technique of the sphere in astronomy) and then about 400 Millions of them are simply passed to a Vertex then Fragment shader performing various coordinates transformation and final adding + merging of colors and brightness to individual pixels.

Basically it is very similar to a point cloud rendering engine, except that all points are transparent, so we must add brightness and colors of all stars ending in the same pixel.
With that simple beginner approach I get 20 FPS on a 4090 using device memory only.

I’d like to go to a next step and compare the performances of a pure software rasterization approach using a compute shader.
So now I’am a bit stuck on a simple step that is saving a simple gradient generated texture in the compute shader to a file representing this skymap.

Code should be quite simple but I don’t find any examples on the web!

Here is how I create the image (I only give main parameters here). It is sucessfully created and no validation errors occurs during execution.

createImage(800, 600, VK_FORMAT_R8G8B8A8_SNORM, VK_IMAGE_TILING_LINEAR,
                              VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |VK_IMAGE_USAGE_TRANSFER_DST_BIT,
                              VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT|VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, image, imageMemory);
        dotDevice.transitionImageLayout(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
        dotDevice.createImageView(image,VK_FORMAT_R8G8B8A8_SNORM, imageView);

As a side note here I could not create the image in TILING OPTIMAL mode because STORAGE flag is activated here so I’am already a bit concerned about performances , but ok I’ll check this in a second phase.

This image is then written in the compute shader , I configured properly the descriptor sets before

layout (binding = 2, rgba8) uniform writeonly image2D result;
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main() {
   ivec2 dim = imageSize(result);
   vec2 uv = vec2(gl_GlobalInvocationID.xy) / dim;   
   imageStore(result,ivec2(gl_GlobalInvocationID.xy),vec4(uv,0.0,1.0));
}

So now I’d like to save the result to a file.

Does someone has an example or book or resources adressing this ?

Thanks :slight_smile:

Maybe I just found something : Vulkan/examples/screenshot/screenshot.cpp at master · SaschaWillems/Vulkan · GitHub

It looks quite verbose and I’d prefer to use stbi_write library. In any case it will be a very good starting point.

Ok actually I figured out a solution using stbi and simple memory mapping of the image :slight_smile:
Everything was actually working, I just forgot to call the submit command to execute the compute shader damn !

Though the image has strange squares, I have to figure out what’s going on there. I looks they are due to the compute shader 16x16 workgroup size.

Ok it was simply the alpha channel fully transparent it seems