I'm using vulkan to create a 3D image (VK_IMAGE_TYPE_3D) with an unsigned 8-bit integer per texel format (VK_FORMAT_R8_UINT). This image is attached to a descriptor set with the type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE which is given to the glsl shader. The reason I need to do this is because the 3D image represents voxel data and the 8 bits for each texel represent an index in a material array for that voxel.
The problem is that I cant find a way to get a 8bit unsigned integer that corresponds to an image coordinate (read data from the image). I have tried the following:
layout (binding = 2, r8ui) uniform uimage3D scene;
and imageLoad(scene, ivec3(0,0,0)).r
But this results in the validation layer error
Type mismatch on descriptor slot 0.2 (expected
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
) but descriptor of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE The Vulkan spec states: layout must be consistent with the layout of the compute shader specified in stage (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-VkComputePipelineCreateInfo-layout-00703)
I don't want to use a storage image though because I need the image to be optimized for fast read-only access.
layout (binding = 2, r8ui) uniform texture3D scene;
results in the shader compile error:
error: 'r8ui' : only apply to images
I don't want to use a storage image though because I need the image to be optimized for fast read-only access.
That's not what using a sampled image does.
If you want to use an image as a sampled image, that means you want to employ the capabilities of samplers. You want to access pixels via normalized coordinates, or you want to do filtering, or texture coordinate wrapping, or automatic mipmap selection, or something like that.
You don't use a sampled image because you want read-only accesses to be faster. That's why storage images have the readonly
layout
qualifier.
If all you want is to have read-only access to a single mipmap level of an image, using integer texel coordinates with no filtering or wrapping, then what you want is a storage image.
However, if you do want to use a sampled image, then you have to follow the rules of sampled images. In particular, you don't specify the format of them in the shader. You specify the general category of the format (floating-point vs. signed integer vs. unsigned integer), but that is specified by the type of the variable (sampler3D
vs. isampler3D
vs. usampler3D
, respectively).
You also need a sampler, either via a combined sampler/image pair specified in the descriptor (which map to the GLSL samplerX
types) or via two separate variables: a texture
type and a sampler
type, which the shader will combine itself.