Skip to content

Instantly share code, notes, and snippets.

@cheery
Last active October 21, 2022 16:14
Show Gist options
  • Save cheery/8d67797fbb8bd6668c38035effcc54f7 to your computer and use it in GitHub Desktop.
Save cheery/8d67797fbb8bd6668c38035effcc54f7 to your computer and use it in GitHub Desktop.
Vulkan abstraction layer warpgpu ideas

WarpGPU abstractions

Vulkan appears to favor abstractions that are transparent and incremental. Meaning:

  • A new abstraction can be introduced in isolation.
  • Individual pieces in the abstraction layer can be left out or or substituted with a different one.

The following abstractions seem evident after studying Vulkan.

Data layouts

Shaders operate on lot of records and packed data during rendering. These layouts can be made useful and reasonable to the user.

Uniform data and descriptor sets, meant to be quick to switch during rendering:

layout (set = 0, location = 0) uniform Transform {
    mat4 projection;
    mat4 modelview;
} t;
layout (set = 1, location = 0) sampler texSampler;
layout (set = 1, location = 1) texture2D tex;

Vertex layouts and attributes:

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;

Push constants:

layout (push_constant) uniform vc {
    float time;
} vc;

The pipeline layout combines push constants and uniforms.

Push constants have the most implicit form of a data layout. They may be grouped and access to them can be restricted to certain parts of the pipeline.

Vertex input state

Shader programs have attribute layouts, and vertex buffers have their own layout.

vertexInputState needs to be build by combining these two layouts. The combination may be straightforward and map the records of the same name together, or then it may be specific and user defined.

DescriptorSet ORM model

It would be likely useful to create an ORM-like model that can be used to record changes into the descriptor set. This would remove the need to do that during updating the descriptor sets:

descset_0.transform = ubo[0 .: Transform.size]
gpu.update([descset_0])

Descriptor sets provide similar problems as push constants, with some complications. First of all the data access is indirect.

Second the descriptor set allocation scheme is pooled with fixed-size pools. This appears to be a detail that is hard to abstract away. It may make sense to expose it to the user in simplified and pooled variations.

Uniform data referenced by descriptors have their own layout, and it makes sense that there should be methods to access this data. The method could be same as it is for the push constants.

Drawables or rendering targets

Vulkan does not have a clear concept of drawable, but it appears to need one. The drawable should communicate the intended role and use of the resource after it has been rendered to.

Render pass

Vulkan render passes require lot of information about attachments, subpasses and dependencies between them, but it is not clear how this could be simplified. I could use some tips here.

It makes sense to hide some of the pipeline state into a render pass because the creation of the pipeline require details about the render pass itself.

The following pipeline configs may be hidden inside the render pass:

  • viewportState
  • rasterizationState
  • multisampleState
  • colorBlendState
  • dynamicState

Framebuffer groups

Framebuffers gather all the render pass attachments together.

Drawables themselves are hardly ever simple. Instead there may be several swapchains, images or buffers that are used and they need to be combined into individual framebuffers.

Graphics pipelines

Pipeline combines the information from the shaders, mesh data, pipeline layout and render pass together.

The pipeline creation should collect the information from the context given to it and allow the user to fill up the remaining information if needed.

Vulkan shader modules come without annotations which is a nice property in general because there's no need for C functions to introspect them.

To allow keeping the creation of pipeline simple, the staging information for each shader could be annotated into the entry points.

Command buffer creation/submission/presentation

The challenges with render passes and command buffers are bound together, mainly related to presentation.

Image acquire and presentation require use of semaphores. In the middle of this all we have a queue submission and possibly we record a command buffer for the frame.

Pipeline barriers and synchronization

Pipeline barriers and synchronization primitives such as fences and semaphores seemed important to abstract away at first. There are potential methods to automate insertion of barriers, but on grand scheme they aren't the first challenge you face when using Vulkan.

There is a hint that barrier insertion can be abstracted away. LunarG validation layers appears to be able to point out the missing barriers. 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment