I develop offscreen Vulkan based render server to perform 2D scene drawing per request.
Ubuntu 18.04 into Docker container
llvmpipe (LLVM 11.0.1, 256 bits)
The scene consists of the same type of meshes and textures of different sizes. Each mesh is bound to its own texture. The maximum number of scene elements is 200. I have just 1 material (vertex + fragment shaders) so I use just 1 pipeline.
High level description of my workfllow:
1) Setup framebuffer and readback image
2) Load all meshes (VBOs and IBOs)
3) Load all textures (images, views, samplers)
4) Create descriptor set for material exposes (mesh transform and texture sampler)
5) Put per-mesh parameters to storage buffer (transform matrices)
6) Update fixed array of texture samplers.
7) Draw each mesh
8) Send readback image to response.
Thats works great on dedicated GPU, llvmpipe
does not support VK_EXT_descriptor_indexing
and shaderSampledImageArrayDynamicIndexing
feature. Its mean I cant indexing (in shaders) texture samler array by value from PushConstants.
#version 450
layout(set = 0, binding = 2) uniform sampler2D textures[200];
layout(push_constant) uniform Constants
{
uint id;
} meta;
void main()
{
// ...
vec4 t = texture(textures, uv); // failed on llvmpipe
// ...
}
To use only one sampler I need:
clear(framebuffer)
for mesh in meshes
{
bind(mesh.vbo)
bind(mesh.ibo)
bind(descriptorset)
update(sampler) // write current mesh texture
submit()
}
read(readback)
...
I dont understand how to setup renderpass
to perform this steps. submit()
in middle of this approach is confuse me.
Could you help me ?
I tried another approach that is based on StorageTexelBuffers.
1. Get max size of texel storage from device limits
(maxTexelBufferElements)
2. Split scene data ito chunks limited by maxTexelBufferElements.
3. Setup framebuffer and clear it
4. Draw a chunk[i]
5. Read back result
In this case samplers usage are not required.
I put N images in 1D array
and pass it to fragment shader. In the shader I calculate index of the specific texel and gather it by imageLoad(...)
layout(location = 0) in vec2 uv;
layout(set = 0, binding = 2, rgba32f) uniform imageBuffer texels;
layout(push_constant) uniform Constants
{
uint id;
uint textureStart;
uint textureWidth;
uint textureHeight;
} meta;
void main()
{
// calculate specific texel real coordinates
uint s = uint(uv.x * float(meta.textureWidth));
uint t = uint(uv.y * float(meta.textureHeight));
// calculate texel index in global array
int index = int(meta.textureStart + s + t * meta.textureWidth);
outColor = imageLoad(noise, tx);
}
Start of the texture is passed in PushConstants
.