Iago talked recently about the work done testing and supporting well known applications, like the Vulkan ports of the Quake1, Quake 2 and Quake3. Let’s go back here to the lastest news on feature and bugfixing work.
Pipeline cache
Pipeline cache objects allow the result of pipeline construction to be reused. Usually (and specifically on our implementation) that means caching compiled shaders. Reuse can be achieved between pipelines creation during the same application run by passing the same pipeline cache object when creating multiple pipelines. Reuse across runs of an application is achieved by retrieving pipeline cache contents in one run of an application, saving the contents, and using them to preinitialize a pipeline cache on a subsequent run.
Note that it may happens that a pipeline cache would not improve the performance of an application once it starts to render. This is because application developers are encouraged to create all the pipelines in advance, to avoid any hiccup during rendering. On that situation pipeline cache would help to reduce load times. In any case, that is not always avoidable. In that case the pipeline cache would allow to reduce the hiccup, as a cache hit is far faster than a shader recompilation.
One specific detail about our implementation is that internally we keep a default pipeline cache, used if the user doesn’t provide a pipeline cache when creating a pipeline, and also to cache the custom shaders we use for internal operations. This allowed to simplify our code, discarding some custom caches that were already implemented.
Uniform/storage texel buffer
Uniform texel buffers define a tightly-packed 1-dimensional linear array of texels, with texels going through format conversion when read in a shader in the same way as they are for an image. They are mostly equivalent to OpenGL buffer texture, so you can see them as textures backed up by a VkBuffer (through a VkBufferView). With uniform texel buffers you can only do a formatted load.
Storage texel buffers are the equivalent concept, but applied to images instead of textures. Unlike uniform texel buffers, they can also be written to in the same way as for storage images.
Multisampling
Multisampling is a technique that allows to reduce aliasing artifacts on images, by by sampling pixel coverage at multiple subpixel locations and then averaging subpixel samples to produce a final color value for each pixel. We have already started working on this feature, and included some patches on the development branch, but it is still a work in progress. Having said so, it is enough to get Sascha Willems’s basic multisampling demo working:
Bugfixing
Again, in addition to work on specific features, we also spent some time fixing specific driver bugs, using failing Vulkan CTS tests as reference. So let’s take a look of some screenshots of Sascha Willem’s demos that are now working:
Next
We plan to work on supporting the following features next:
- Robust access
- Multisample (finish it)
Previous updates
Just in case you missed any of the updates of the vulkan driver so far:
Vulkan raspberry pi first triangle
Vulkan update now with added source code
v3dv status update 2020-07-01
V3DV Vulkan driver update: VkQuake1-3 now working
Hello,
I’m running Sascha’s examples on latest wip/igalia/v3dv #357bd7, which is amazing.
Then I got `wgpu-rs` to cross compile with the vulkan features. Their `hello` and `hello-compute` (!) example works fine. However, any demo displaying things ‘Failed to acquire next swap chain texture!: Timeout’.
I have all the logs and traces.
Can you point your finger to it? Should I file maybe an issue on mesa or wgpu-rs?
cube example
“`trace.ron
[
Init(
desc: (
features: (
bits: 0,
),
limits: (
max_bind_groups: 4,
max_dynamic_uniform_buffers_per_pipeline_layout: 8,
max_dynamic_storage_buffers_per_pipeline_layout: 4,
max_sampled_textures_per_shader_stage: 16,
max_samplers_per_shader_stage: 16,
max_storage_buffers_per_shader_stage: 4,
max_storage_textures_per_shader_stage: 4,
max_uniform_buffers_per_shader_stage: 12,
max_uniform_buffer_binding_size: 16384,
max_push_constant_size: 0,
),
shader_validation: true,
),
backend: Vulkan,
),
CreateSwapChain(Id(0, 1, Vulkan), (
usage: (
bits: 16,
),
format: Bgra8UnormSrgb,
width: 800,
height: 600,
present_mode: Mailbox,
)),
CreateBuffer(Id(0, 1, Vulkan), (
label: “Vertex Buffer”,
size: 580,
usage: (
bits: 40,
),
mapped_at_creation: false,
)),
WriteBuffer(
id: Id(0, 1, Vulkan),
data: “data1.bin”,
range: (
start: 0,
end: 580,
),
queued: true,
),
CreateBuffer(Id(1, 1, Vulkan), (
label: “Index Buffer”,
size: 76,
usage: (
bits: 24,
),
mapped_at_creation: false,
)),
WriteBuffer(
id: Id(1, 1, Vulkan),
data: “data2.bin”,
range: (
start: 0,
end: 76,
),
queued: true,
),
CreateBindGroupLayout(Id(0, 1, Vulkan), (
label: None,
entries: [
(
binding: 0,
visibility: (
bits: 1,
),
ty: UniformBuffer(
dynamic: false,
min_binding_size: Some(64),
),
count: None,
),
(
binding: 1,
visibility: (
bits: 2,
),
ty: SampledTexture(
dimension: D2,
component_type: Float,
multisampled: false,
),
count: None,
),
(
binding: 2,
visibility: (
bits: 2,
),
ty: Sampler(
comparison: false,
),
count: None,
),
],
)),
CreatePipelineLayout(Id(0, 1, Vulkan), (
bind_group_layouts: [
Id(0, 1, Vulkan),
],
push_constant_ranges: [],
)),
CreateTexture(Id(0, 1, Vulkan), (
label: “”,
size: (
width: 256,
height: 256,
depth: 1,
),
mip_level_count: 1,
sample_count: 1,
dimension: D2,
format: Rgba8UnormSrgb,
usage: (
bits: 6,
),
)),
CreateTextureView(
id: Id(0, 1, Vulkan),
parent_id: Id(0, 1, Vulkan),
desc: None,
),
WriteTexture(
to: (
texture: Id(0, 1, Vulkan),
mip_level: 0,
origin: (
x: 0,
y: 0,
z: 0,
),
),
data: “data3.bin”,
layout: (
offset: 0,
bytes_per_row: 1024,
rows_per_image: 0,
),
size: (
width: 256,
height: 256,
depth: 1,
),
),
CreateSampler(Id(0, 1, Vulkan), (
label: “”,
address_mode_u: ClampToEdge,
address_mode_v: ClampToEdge,
address_mode_w: ClampToEdge,
mag_filter: Nearest,
min_filter: Linear,
mipmap_filter: Nearest,
lod_min_clamp: 0,
lod_max_clamp: 340282350000000000000000000000000000000,
compare: None,
anisotropy_clamp: None,
)),
CreateBuffer(Id(2, 1, Vulkan), (
label: “Uniform Buffer”,
size: 68,
usage: (
bits: 72,
),
mapped_at_creation: false,
)),
WriteBuffer(
id: Id(2, 1, Vulkan),
data: “data4.bin”,
range: (
start: 0,
end: 68,
),
queued: true,
),
CreateBindGroup(Id(0, 1, Vulkan), (
label: None,
layout: Id(0, 1, Vulkan),
entries: [
(
binding: 0,
resource: Buffer((
buffer_id: Id(2, 1, Vulkan),
offset: 0,
size: None,
)),
),
(
binding: 1,
resource: TextureView(Id(0, 1, Vulkan)),
),
(
binding: 2,
resource: Sampler(Id(0, 1, Vulkan)),
),
],
)),
CreateShaderModule(
id: Id(0, 1, Vulkan),
data: “data5.spv”,
),
CreateShaderModule(
id: Id(1, 1, Vulkan),
data: “data6.spv”,
),
CreateRenderPipeline(Id(0, 1, Vulkan), (
layout: Id(0, 1, Vulkan),
vertex_stage: (
module: Id(0, 1, Vulkan),
entry_point: “main”,
),
fragment_stage: Some((
module: Id(1, 1, Vulkan),
entry_point: “main”,
)),
rasterization_state: Some((
front_face: Ccw,
cull_mode: Back,
clamp_depth: false,
depth_bias: 0,
depth_bias_slope_scale: 0,
depth_bias_clamp: 0,
)),
primitive_topology: TriangleList,
color_states: [
(
format: Bgra8UnormSrgb,
alpha_blend: (
src_factor: One,
dst_factor: Zero,
operation: Add,
),
color_blend: (
src_factor: One,
dst_factor: Zero,
operation: Add,
),
write_mask: (
bits: 15,
),
),
],
depth_stencil_state: None,
vertex_state: (
index_format: Uint16,
vertex_buffers: [
(
stride: 24,
step_mode: Vertex,
attributes: [
(
offset: 0,
format: Float4,
shader_location: 0,
),
(
offset: 16,
format: Float2,
shader_location: 1,
),
],
),
],
),
sample_count: 1,
sample_mask: 4294967295,
alpha_to_coverage_enabled: false,
)),
DestroyShaderModule(Id(1, 1, Vulkan)),
DestroyShaderModule(Id(0, 1, Vulkan)),
WriteBuffer(
id: Id(2, 1, Vulkan),
data: “data7.bin”,
range: (
start: 0,
end: 64,
),
queued: true,
),
CreateSwapChain(Id(0, 1, Vulkan), (
usage: (
bits: 16,
),
format: Bgra8UnormSrgb,
width: 800,
height: 600,
present_mode: Mailbox,
)),
GetSwapChainTexture(
id: None,
parent_id: Id(0, 1, Vulkan),
),
CreateSwapChain(Id(0, 1, Vulkan), (
usage: (
bits: 16,
),
format: Bgra8UnormSrgb,
width: 800,
height: 600,
present_mode: Mailbox,
)),
GetSwapChainTexture(
id: None,
parent_id: Id(0, 1, Vulkan),
),
“`
Hi, thanks for the positive feedback.
Not sure why that happens. If that is working on any other vulkan driver, then I think that it makes sense to create an issue on mesa. As v3dv is not still integrated on mesa master, you can create an issue here:
https://gitlab.freedesktop.org/apinheiro/mesa/-/issues
Having said so, as mentioned, and even warned by the driver itself, the driver is still a work in progress, so unless a quick skim get us a hint to where to fix the issue, our priority would be focused on getting the core features and CTS tests working.
Thanks for testing the driver.
What steps did you take to get wgpu-rs running on a pi? I followed the v3d3 installation guide, and managed to get the Willem demos running, then went straight to wgpu-rs/examples, but couldn’t get even the “hello” to run.
And to Infapi00, amazing work! I’m so impressed that I’m able to run Vulkan on my tiny little Pi4!
I used `cross` with a Dockerfile for these armhf headers:
“`
FROM rustembedded/cross:armv7-unknown-linux-gnueabihf-0.2.1
RUN dpkg –add-architecture armhf && \
apt-get update && \
apt-get install -y libasound2-dev:armhf libx11-dev:armhf python3:armhf libx11-xcb-dev:armhf libxcb-composite0-dev:armhf
# x11 not found
ENV PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/arm-linux-gnueabihf/pkgconfig
“`
https://www.youtube.com/watch?v=zjodr3Q9pqg
This is a video showing the current driver running vkOpenarena. There are some weird glitches, but the performance is already better than opengl2. Keep it up guys!
Oh nice, thanks for posting!
About the glitches, it seems that there is something wrong when rendering the sky. We already noted that when running vkQuake3, so we already have it on our radar. We will take a look when we got all the vulkan CTS tests (needed for conformance) passing.
Again, thanks.