Files
test/source/blender/gpu/tests/storage_buffer_test.cc

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

211 lines
5.6 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
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 "testing/testing.h"
#include "GPU_storage_buffer.hh"
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 "BLI_math_vector.hh"
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 "BLI_vector.hh"
#include "gpu_testing.hh"
namespace blender::gpu::tests {
constexpr size_t SIZE = 128;
constexpr size_t SIZE_IN_BYTES = SIZE * sizeof(int);
static Vector<int32_t> test_data()
{
Vector<int32_t> data;
for (int i : IndexRange(SIZE)) {
data.append(i);
}
return data;
}
static void test_storage_buffer_create_update_read()
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
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
EXPECT_NE(ssbo, nullptr);
/* Upload some dummy data. */
const Vector<int32_t> data = test_data();
GPU_storagebuf_update(ssbo, data.data());
/* Read back data from SSBO. */
Vector<int32_t> read_data;
read_data.resize(SIZE, 0);
GPU_storagebuf_read(ssbo, read_data.data());
2023-02-27 21:44:59 +11:00
/* Check if data is the same. */
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
for (int i : IndexRange(SIZE)) {
EXPECT_EQ(data[i], read_data[i]);
}
GPU_storagebuf_free(ssbo);
}
GPU_TEST(storage_buffer_create_update_read);
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
static void test_storage_buffer_clear_zero()
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
EXPECT_NE(ssbo, nullptr);
/* Upload some dummy data. */
const Vector<int32_t> data = test_data();
GPU_storagebuf_update(ssbo, data.data());
GPU_storagebuf_clear_to_zero(ssbo);
/* Read back data from SSBO. */
Vector<int32_t> read_data;
read_data.resize(SIZE, 0);
GPU_storagebuf_read(ssbo, read_data.data());
/* Check if data is the same. */
for (int i : IndexRange(SIZE)) {
EXPECT_EQ(0, read_data[i]);
}
GPU_storagebuf_free(ssbo);
}
GPU_TEST(storage_buffer_clear_zero);
static void test_storage_buffer_clear()
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
EXPECT_NE(ssbo, nullptr);
GPU_storagebuf_clear(ssbo, 157255);
/* Read back data from SSBO. */
Vector<int32_t> read_data;
read_data.resize(SIZE, 0);
GPU_storagebuf_read(ssbo, read_data.data());
/* Check if datatest_ is the same. */
for (int i : IndexRange(SIZE)) {
EXPECT_EQ(157255, read_data[i]);
}
GPU_storagebuf_free(ssbo);
}
GPU_TEST(storage_buffer_clear);
static void test_storage_buffer_clear_byte_pattern()
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
EXPECT_NE(ssbo, nullptr);
/* Tests a different clear command on Metal. */
GPU_storagebuf_clear(ssbo, 0xFCFCFCFCu);
/* Read back data from SSBO. */
Vector<int32_t> read_data;
read_data.resize(SIZE, 0);
GPU_storagebuf_read(ssbo, read_data.data());
/* Check if datatest_ is the same. */
for (int i : IndexRange(SIZE)) {
EXPECT_EQ(0xFCFCFCFCu, read_data[i]);
}
GPU_storagebuf_free(ssbo);
}
GPU_TEST(storage_buffer_clear_byte_pattern);
static void test_storage_buffer_copy_from_vertex_buffer()
{
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE_IN_BYTES, nullptr, GPU_USAGE_STATIC, __func__);
EXPECT_NE(ssbo, nullptr);
/* Create vertex buffer. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
VertBuf *vbo = GPU_vertbuf_create_with_format(format);
2024-06-08 00:25:40 +02:00
GPU_vertbuf_data_alloc(*vbo, 4);
struct Vert {
float2 pos;
float4 color;
};
Vert data[4] = {
{float2(-1.0, -1.0), float4(0.0, 0.0, 0.0, 1.0)},
{float2(1.0, -1.0), float4(1.0, 0.0, 0.0, 1.0)},
{float2(1.0, 1.0), float4(1.0, 1.0, 0.0, 1.0)},
{float2(-1.0, 1.0), float4(0.0, 1.0, 0.0, 1.0)},
};
for (int i : IndexRange(4)) {
GPU_vertbuf_vert_set(vbo, i, &data[i]);
}
float *expected_data = static_cast<float *>(static_cast<void *>(&data));
Vector<float> read_data;
read_data.resize(SIZE, 0);
/* Copy vertex buffer to storage buffer. */
{
GPU_storagebuf_clear_to_zero(ssbo);
GPU_storagebuf_copy_sub_from_vertbuf(ssbo, vbo, 0, 0, sizeof(data));
/* Validate content of SSBO. */
GPU_storagebuf_read(ssbo, read_data.data());
EXPECT_EQ_ARRAY(expected_data, read_data.data(), 24);
for (int i : IndexRange(24, SIZE - 24)) {
EXPECT_EQ(0.0, read_data[i]);
}
}
/* Copy vertex buffer to storage buffer with 16 bytes of offset. */
{
GPU_storagebuf_clear_to_zero(ssbo);
GPU_storagebuf_copy_sub_from_vertbuf(ssbo, vbo, 16, 0, sizeof(data));
/* Validate content of SSBO. */
GPU_storagebuf_read(ssbo, read_data.data());
for (int i : IndexRange(4)) {
EXPECT_EQ(0.0, read_data[i]);
}
float *expected_data = static_cast<float *>(static_cast<void *>(&data));
EXPECT_EQ_ARRAY(expected_data, &(read_data.data()[4]), 24);
for (int i : IndexRange(28, SIZE - 28)) {
EXPECT_EQ(0.0, read_data[i]);
}
}
/* Partially Copy vertex buffer to storage buffer with 16 bytes of offset. */
{
GPU_storagebuf_clear_to_zero(ssbo);
GPU_storagebuf_copy_sub_from_vertbuf(ssbo, vbo, 16, sizeof(Vert), sizeof(data) / 2);
/* Validate content of SSBO. */
GPU_storagebuf_read(ssbo, read_data.data());
for (int i : IndexRange(4)) {
EXPECT_EQ(0.0, read_data[i]);
}
float *expected_data = static_cast<float *>(static_cast<void *>(&data));
EXPECT_EQ_ARRAY(&expected_data[6], &(read_data.data()[4]), 12);
for (int i : IndexRange(16, SIZE - 16)) {
EXPECT_EQ(0.0, read_data[i]);
}
}
GPU_vertbuf_discard(vbo);
GPU_storagebuf_free(ssbo);
}
GPU_TEST(storage_buffer_copy_from_vertex_buffer);
2023-02-27 21:44:59 +11:00
} // namespace blender::gpu::tests