Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do UBOs/SSBOs differ from Vulkan's shader memory bindings?

Tags:

opengl

vulkan

In the article on Imagination's website, I've read the following paragraph:

For example, there are no glUniform*() equivalent entry points in Vulkan; instead, writing to GPU memory is the only way to pass data to shaders.

When you call glUniform*(), the OpenGL ES driver typically needs to allocate a driver managed buffer and copy data to it, the management of which incurs CPU overhead. In Vulkan, you simply map the memory address and write to that memory location directly.

Is there any difference between that and using Uniform Buffers? They are also allocated explicitely and can carry arbitrary data. Since Uniform Buffers are quite limited in size, perhaps Shader Storage Buffers are a better analogy.

like image 283
Bartek Banachewicz Avatar asked Mar 03 '15 15:03

Bartek Banachewicz


Video Answer


1 Answers

From what I understand, this is not glUniform*() specific: glUniform*() is merely an example used by the author of the article to illustrate the way Vulkan works with regards to communication between the host and the GPU.

When you call glUniform*(), the OpenGL ES driver typically needs to allocate a driver managed buffer and copy data to it, the management of which incurs CPU overhead.

In this scenario, when a user calls glUniform*() with some data, that data is first copied to a buffer owned by the OpenGL implementation. This buffer is probably pinned, and can then be used by the driver to transfer the data through DMA to the device. That's two steps:

  1. Copy user data to driver buffer;
  2. Transfer buffer contents to GPU through DMA.

In Vulkan, you simply map the memory address and write to that memory location directly.

In this scenario, there is no intermediate copy of the user data. You ask Vulkan to map a region into the host's virtual address space, which you directly write to. The data gets to the device through DMA in a completely transparent way for the user.

From a performance standpoint, the benefits are obvious: zero copy. It also means the Vulkan implementation can be simpler, as it does not need to manage an intermediate buffer.

As the specs have not been released yet, here's a fictitious example of what it could look like:

// Assume Lights is some kind of handle to your buffer/data
float4* lights = vkMap(Lights);

for (int i = 0; i < light_count; ++i) {
    // Goes directly to the device
    lights[i] = make_light(/* stuff */);
}

vkUnmap(lights);
like image 183
user703016 Avatar answered Oct 13 '22 10:10

user703016