Files
test/source/blender/gpu/vulkan/vk_storage_buffer.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

105 lines
2.9 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
Vulkan: Initial Compute Shaders support This patch adds initial support for compute shaders to the vulkan backend. As the development is oriented to the test- cases we have the implementation is limited to what is used there. It has been validated that with this patch that the following test cases are running as expected - `GPUVulkanTest.gpu_shader_compute_vbo` - `GPUVulkanTest.gpu_shader_compute_ibo` - `GPUVulkanTest.gpu_shader_compute_ssbo` - `GPUVulkanTest.gpu_storage_buffer_create_update_read` - `GPUVulkanTest.gpu_shader_compute_2d` This patch includes: - Allocating VkBuffer on device. - Uploading data from CPU to VkBuffer. - Binding VkBuffer as SSBO to a compute shader. - Execute compute shader and altering VkBuffer. - Download the VkBuffer to CPU ram. - Validate that it worked. - Use device only vertex buffer as SSBO - Use device only index buffer as SSBO - Use device only image buffers GHOST API has been changed as the original design was created before we even had support for compute shaders in blender. The function `GHOST_getVulkanBackbuffer` has been separated to retrieve the command buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order to do correct command buffer processing we needed access to the queue owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles` function. Open topics (not considered part of this patch) - Memory barriers & command buffer encoding - Indirect compute dispatching - Rest of the test cases - Data conversions when requested data format is different than on device. - GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices. NVIDIA doesn't seem to support 1d textures. Pull-request: #104518
2023-02-21 15:03:12 +01:00
#include "vk_shader.hh"
#include "vk_shader_interface.hh"
#include "vk_staging_buffer.hh"
#include "vk_state_manager.hh"
#include "vk_vertex_buffer.hh"
#include "vk_storage_buffer.hh"
namespace blender::gpu {
VKStorageBuffer::VKStorageBuffer(size_t size, GPUUsageType usage, const char *name)
: StorageBuf(size, name), usage_(usage)
{
}
Vulkan: Initial Compute Shaders support This patch adds initial support for compute shaders to the vulkan backend. As the development is oriented to the test- cases we have the implementation is limited to what is used there. It has been validated that with this patch that the following test cases are running as expected - `GPUVulkanTest.gpu_shader_compute_vbo` - `GPUVulkanTest.gpu_shader_compute_ibo` - `GPUVulkanTest.gpu_shader_compute_ssbo` - `GPUVulkanTest.gpu_storage_buffer_create_update_read` - `GPUVulkanTest.gpu_shader_compute_2d` This patch includes: - Allocating VkBuffer on device. - Uploading data from CPU to VkBuffer. - Binding VkBuffer as SSBO to a compute shader. - Execute compute shader and altering VkBuffer. - Download the VkBuffer to CPU ram. - Validate that it worked. - Use device only vertex buffer as SSBO - Use device only index buffer as SSBO - Use device only image buffers GHOST API has been changed as the original design was created before we even had support for compute shaders in blender. The function `GHOST_getVulkanBackbuffer` has been separated to retrieve the command buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order to do correct command buffer processing we needed access to the queue owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles` function. Open topics (not considered part of this patch) - Memory barriers & command buffer encoding - Indirect compute dispatching - Rest of the test cases - Data conversions when requested data format is different than on device. - GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices. NVIDIA doesn't seem to support 1d textures. Pull-request: #104518
2023-02-21 15:03:12 +01:00
void VKStorageBuffer::update(const void *data)
{
VKContext &context = *VKContext::get();
ensure_allocated();
VKStagingBuffer staging_buffer(buffer_, VKStagingBuffer::Direction::HostToDevice);
staging_buffer.host_buffer_get().update_immediately(data);
staging_buffer.copy_to_device(context);
}
void VKStorageBuffer::ensure_allocated()
Vulkan: Initial Compute Shaders support This patch adds initial support for compute shaders to the vulkan backend. As the development is oriented to the test- cases we have the implementation is limited to what is used there. It has been validated that with this patch that the following test cases are running as expected - `GPUVulkanTest.gpu_shader_compute_vbo` - `GPUVulkanTest.gpu_shader_compute_ibo` - `GPUVulkanTest.gpu_shader_compute_ssbo` - `GPUVulkanTest.gpu_storage_buffer_create_update_read` - `GPUVulkanTest.gpu_shader_compute_2d` This patch includes: - Allocating VkBuffer on device. - Uploading data from CPU to VkBuffer. - Binding VkBuffer as SSBO to a compute shader. - Execute compute shader and altering VkBuffer. - Download the VkBuffer to CPU ram. - Validate that it worked. - Use device only vertex buffer as SSBO - Use device only index buffer as SSBO - Use device only image buffers GHOST API has been changed as the original design was created before we even had support for compute shaders in blender. The function `GHOST_getVulkanBackbuffer` has been separated to retrieve the command buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order to do correct command buffer processing we needed access to the queue owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles` function. Open topics (not considered part of this patch) - Memory barriers & command buffer encoding - Indirect compute dispatching - Rest of the test cases - Data conversions when requested data format is different than on device. - GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices. NVIDIA doesn't seem to support 1d textures. Pull-request: #104518
2023-02-21 15:03:12 +01:00
{
if (!buffer_.is_allocated()) {
allocate();
Vulkan: Initial Compute Shaders support This patch adds initial support for compute shaders to the vulkan backend. As the development is oriented to the test- cases we have the implementation is limited to what is used there. It has been validated that with this patch that the following test cases are running as expected - `GPUVulkanTest.gpu_shader_compute_vbo` - `GPUVulkanTest.gpu_shader_compute_ibo` - `GPUVulkanTest.gpu_shader_compute_ssbo` - `GPUVulkanTest.gpu_storage_buffer_create_update_read` - `GPUVulkanTest.gpu_shader_compute_2d` This patch includes: - Allocating VkBuffer on device. - Uploading data from CPU to VkBuffer. - Binding VkBuffer as SSBO to a compute shader. - Execute compute shader and altering VkBuffer. - Download the VkBuffer to CPU ram. - Validate that it worked. - Use device only vertex buffer as SSBO - Use device only index buffer as SSBO - Use device only image buffers GHOST API has been changed as the original design was created before we even had support for compute shaders in blender. The function `GHOST_getVulkanBackbuffer` has been separated to retrieve the command buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order to do correct command buffer processing we needed access to the queue owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles` function. Open topics (not considered part of this patch) - Memory barriers & command buffer encoding - Indirect compute dispatching - Rest of the test cases - Data conversions when requested data format is different than on device. - GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices. NVIDIA doesn't seem to support 1d textures. Pull-request: #104518
2023-02-21 15:03:12 +01:00
}
}
void VKStorageBuffer::allocate()
{
const bool is_host_visible = false;
const VkBufferUsageFlags buffer_usage_flags = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
buffer_.create(size_in_bytes_, usage_, buffer_usage_flags, is_host_visible);
debug::object_label(buffer_.vk_handle(), name_);
}
Vulkan: Initial Compute Shaders support This patch adds initial support for compute shaders to the vulkan backend. As the development is oriented to the test- cases we have the implementation is limited to what is used there. It has been validated that with this patch that the following test cases are running as expected - `GPUVulkanTest.gpu_shader_compute_vbo` - `GPUVulkanTest.gpu_shader_compute_ibo` - `GPUVulkanTest.gpu_shader_compute_ssbo` - `GPUVulkanTest.gpu_storage_buffer_create_update_read` - `GPUVulkanTest.gpu_shader_compute_2d` This patch includes: - Allocating VkBuffer on device. - Uploading data from CPU to VkBuffer. - Binding VkBuffer as SSBO to a compute shader. - Execute compute shader and altering VkBuffer. - Download the VkBuffer to CPU ram. - Validate that it worked. - Use device only vertex buffer as SSBO - Use device only index buffer as SSBO - Use device only image buffers GHOST API has been changed as the original design was created before we even had support for compute shaders in blender. The function `GHOST_getVulkanBackbuffer` has been separated to retrieve the command buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order to do correct command buffer processing we needed access to the queue owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles` function. Open topics (not considered part of this patch) - Memory barriers & command buffer encoding - Indirect compute dispatching - Rest of the test cases - Data conversions when requested data format is different than on device. - GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices. NVIDIA doesn't seem to support 1d textures. Pull-request: #104518
2023-02-21 15:03:12 +01:00
void VKStorageBuffer::bind(int slot)
{
VKContext &context = *VKContext::get();
Vulkan: Refactor resource binding Resource binding was over-complicated as I didn't understood the state manager and vulkan to make the correct decisions at that time. This refactor will remove a lot of the complexity and improves the performance. **Performance** The performance improvement is noticeable in complex grease pencil scenes. Grease pencil benchmark file picknick: - `NVIDIA Quadro RTX 6000` 17 fps -> 24 fps - `Intel(R) Arc(tm) A750 Graphics (DG2)` 6 -> 21 fps **Bottle-neck** The performance improvements originates from moving the update entry point from state manager to shader interface. The previous implementation (state manager) had to loop over all the bound resources and find in the shader interface where it was located in the descriptor set. Ignoring resources that were not used by the shader. But also making it hard to determine if descriptor sets actually changed. Previous implementation assumed descriptor sets always changed. When descriptor set changed a new descriptor set needed to be allocated. Most drivers this is a fast operation, but on Intel/Mesa this was measurable slow. Using an allocation pool doesn't fit the Vulkan API as you are only able to reuse when the layout matches exactly. Of course doable, but requires another structure to keep track of the actual layouts. **Solution** By using the shader interface as entry point we can: 1. Keep track if there are any changes in the state manager. If not and the layout is the same, the previous shader can be reused. 2. In stead of looping over each bound resource, we loop over bind points. **Future extensions** Bundle all descriptor set uploads just before use. This would be more in line with how 'modern' Vulkan should be implemented. This PR already separates the uploading from the updating and technically allows to upload more than one descriptor set. Instead of looking 1 set back we should measure if we can handle multiple or keep track of the different layouts resources to improve the performance even further. Optional use `VK_KHR_descriptor_buffer` when available. Pull Request: https://projects.blender.org/blender/blender/pulls/128068
2024-09-26 10:59:45 +02:00
context.state_manager_get().storage_buffer_bind(
BindSpaceStorageBuffers::Type::StorageBuffer, this, slot);
}
void VKStorageBuffer::unbind()
{
Vulkan: Refactor resource binding Resource binding was over-complicated as I didn't understood the state manager and vulkan to make the correct decisions at that time. This refactor will remove a lot of the complexity and improves the performance. **Performance** The performance improvement is noticeable in complex grease pencil scenes. Grease pencil benchmark file picknick: - `NVIDIA Quadro RTX 6000` 17 fps -> 24 fps - `Intel(R) Arc(tm) A750 Graphics (DG2)` 6 -> 21 fps **Bottle-neck** The performance improvements originates from moving the update entry point from state manager to shader interface. The previous implementation (state manager) had to loop over all the bound resources and find in the shader interface where it was located in the descriptor set. Ignoring resources that were not used by the shader. But also making it hard to determine if descriptor sets actually changed. Previous implementation assumed descriptor sets always changed. When descriptor set changed a new descriptor set needed to be allocated. Most drivers this is a fast operation, but on Intel/Mesa this was measurable slow. Using an allocation pool doesn't fit the Vulkan API as you are only able to reuse when the layout matches exactly. Of course doable, but requires another structure to keep track of the actual layouts. **Solution** By using the shader interface as entry point we can: 1. Keep track if there are any changes in the state manager. If not and the layout is the same, the previous shader can be reused. 2. In stead of looping over each bound resource, we loop over bind points. **Future extensions** Bundle all descriptor set uploads just before use. This would be more in line with how 'modern' Vulkan should be implemented. This PR already separates the uploading from the updating and technically allows to upload more than one descriptor set. Instead of looking 1 set back we should measure if we can handle multiple or keep track of the different layouts resources to improve the performance even further. Optional use `VK_KHR_descriptor_buffer` when available. Pull Request: https://projects.blender.org/blender/blender/pulls/128068
2024-09-26 10:59:45 +02:00
VKContext *context = VKContext::get();
if (context) {
context->state_manager_get().storage_buffer_unbind(this);
}
}
void VKStorageBuffer::clear(uint32_t clear_value)
{
ensure_allocated();
VKContext &context = *VKContext::get();
buffer_.clear(context, clear_value);
}
void VKStorageBuffer::copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size)
{
ensure_allocated();
VKVertexBuffer &src_vertex_buffer = *unwrap(src);
src_vertex_buffer.upload();
render_graph::VKCopyBufferNode::CreateInfo copy_buffer = {};
copy_buffer.src_buffer = src_vertex_buffer.vk_handle();
copy_buffer.dst_buffer = vk_handle();
copy_buffer.region.srcOffset = src_offset;
copy_buffer.region.dstOffset = dst_offset;
copy_buffer.region.size = copy_size;
VKContext &context = *VKContext::get();
context.render_graph.add_node(copy_buffer);
}
GPU: Add explicit API to sync storage buffer back to host PR Introduces GPU_storagebuf_sync_to_host as an explicit routine to flush GPU-resident storage buffer memory back to the host within the GPU command stream. The previous implmentation relied on implicit synchronization of resources using OpenGL barriers which does not match the paradigm of explicit APIs, where indiviaul resources may need to be tracked. This patch ensures GPU_storagebuf_read can be called without stalling the GPU pipeline while work finishes executing. There are two possible use cases: 1) If GPU_storagebuf_read is called AFTER an explicit call to GPU_storagebuf_sync_to_host, the read will be synchronized. If the dependent work is still executing on the GPU, the host will stall until GPU work has completed and results are available. 2) If GPU_storagebuf_read is called WITHOUT an explicit call to GPU_storagebuf_sync_to_host, the read will be asynchronous and whatever memory is visible to the host at that time will be used. (This is the same as assuming a sync event has already been signalled.) This patch also addresses a gap in the Metal implementation where there was missing read support for GPU-only storage buffers. This routine now uses a staging buffer to copy results if no host-visible buffer was available. Reading from a GPU-only storage buffer will always stall the host, as it is not possible to pre-flush results, as no host-resident buffer is available. Authored by Apple: Michael Parkin-White Pull Request: https://projects.blender.org/blender/blender/pulls/113456
2023-10-20 17:04:36 +02:00
void VKStorageBuffer::async_flush_to_host()
{
GPU_memory_barrier(GPU_BARRIER_BUFFER_UPDATE);
}
Vulkan: Initial Compute Shaders support This patch adds initial support for compute shaders to the vulkan backend. As the development is oriented to the test- cases we have the implementation is limited to what is used there. It has been validated that with this patch that the following test cases are running as expected - `GPUVulkanTest.gpu_shader_compute_vbo` - `GPUVulkanTest.gpu_shader_compute_ibo` - `GPUVulkanTest.gpu_shader_compute_ssbo` - `GPUVulkanTest.gpu_storage_buffer_create_update_read` - `GPUVulkanTest.gpu_shader_compute_2d` This patch includes: - Allocating VkBuffer on device. - Uploading data from CPU to VkBuffer. - Binding VkBuffer as SSBO to a compute shader. - Execute compute shader and altering VkBuffer. - Download the VkBuffer to CPU ram. - Validate that it worked. - Use device only vertex buffer as SSBO - Use device only index buffer as SSBO - Use device only image buffers GHOST API has been changed as the original design was created before we even had support for compute shaders in blender. The function `GHOST_getVulkanBackbuffer` has been separated to retrieve the command buffer without a backbuffer (`GHOST_getVulkanCommandBuffer`). In order to do correct command buffer processing we needed access to the queue owned by GHOST. This is returned as part of the `GHOST_getVulkanHandles` function. Open topics (not considered part of this patch) - Memory barriers & command buffer encoding - Indirect compute dispatching - Rest of the test cases - Data conversions when requested data format is different than on device. - GPUVulkanTest.gpu_shader_compute_1d is supported on AMD devices. NVIDIA doesn't seem to support 1d textures. Pull-request: #104518
2023-02-21 15:03:12 +01:00
void VKStorageBuffer::read(void *data)
{
ensure_allocated();
VKContext &context = *VKContext::get();
VKStagingBuffer staging_buffer(buffer_, VKStagingBuffer::Direction::DeviceToHost);
staging_buffer.copy_from_device(context);
staging_buffer.host_buffer_get().read(context, data);
}
} // namespace blender::gpu