diff --git a/source/blender/gpu/tests/storage_buffer_test.cc b/source/blender/gpu/tests/storage_buffer_test.cc index 35d0b8f1a1a..3903fade393 100644 --- a/source/blender/gpu/tests/storage_buffer_test.cc +++ b/source/blender/gpu/tests/storage_buffer_test.cc @@ -47,4 +47,52 @@ static void test_storage_buffer_create_update_read() GPU_TEST(storage_buffer_create_update_read); +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 data = test_data(); + GPU_storagebuf_update(ssbo, data.data()); + GPU_storagebuf_clear_to_zero(ssbo); + + /* Read back data from SSBO. */ + Vector 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 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); + } // namespace blender::gpu::tests diff --git a/source/blender/gpu/vulkan/vk_buffer.cc b/source/blender/gpu/vulkan/vk_buffer.cc index a5afcde7162..feb5ca9c9a0 100644 --- a/source/blender/gpu/vulkan/vk_buffer.cc +++ b/source/blender/gpu/vulkan/vk_buffer.cc @@ -84,6 +84,12 @@ void VKBuffer::update(const void *data) const memcpy(mapped_memory_, data, size_in_bytes_); } +void VKBuffer::clear(VKContext &context, uint32_t clear_value) +{ + VKCommandBuffer &command_buffer = context.command_buffer_get(); + command_buffer.fill(*this, clear_value); +} + void VKBuffer::read(void *data) const { BLI_assert_msg(is_mapped(), "Cannot read a non-mapped buffer."); diff --git a/source/blender/gpu/vulkan/vk_buffer.hh b/source/blender/gpu/vulkan/vk_buffer.hh index 917103114a5..dac3519fbb8 100644 --- a/source/blender/gpu/vulkan/vk_buffer.hh +++ b/source/blender/gpu/vulkan/vk_buffer.hh @@ -35,6 +35,7 @@ class VKBuffer { int64_t size, GPUUsageType usage, VkBufferUsageFlagBits buffer_usage); + void clear(VKContext &context, uint32_t clear_value); void update(const void *data) const; void read(void *data) const; bool free(VKContext &context); diff --git a/source/blender/gpu/vulkan/vk_command_buffer.cc b/source/blender/gpu/vulkan/vk_command_buffer.cc index b4526df6aba..af8d39bcf7b 100644 --- a/source/blender/gpu/vulkan/vk_command_buffer.cc +++ b/source/blender/gpu/vulkan/vk_command_buffer.cc @@ -86,6 +86,11 @@ void VKCommandBuffer::push_constants(const VKPushConstants &push_constants, push_constants.data()); } +void VKCommandBuffer::fill(VKBuffer &buffer, uint32_t clear_data) +{ + vkCmdFillBuffer(vk_command_buffer_, buffer.vk_handle(), 0, buffer.size_in_bytes(), clear_data); +} + void VKCommandBuffer::copy(VKBuffer &dst_buffer, VKTexture &src_texture, Span regions) diff --git a/source/blender/gpu/vulkan/vk_command_buffer.hh b/source/blender/gpu/vulkan/vk_command_buffer.hh index 0f5f47a423a..103f4ac2300 100644 --- a/source/blender/gpu/vulkan/vk_command_buffer.hh +++ b/source/blender/gpu/vulkan/vk_command_buffer.hh @@ -51,6 +51,7 @@ class VKCommandBuffer : NonCopyable, NonMovable { void pipeline_barrier(VkPipelineStageFlags source_stages, VkPipelineStageFlags destination_stages); void pipeline_barrier(Span image_memory_barriers); + void fill(VKBuffer &buffer, uint32_t data); /** * Stop recording commands, encode + send the recordings to Vulkan, wait for the until the diff --git a/source/blender/gpu/vulkan/vk_storage_buffer.cc b/source/blender/gpu/vulkan/vk_storage_buffer.cc index 5ab293bef6a..fd89fc38296 100644 --- a/source/blender/gpu/vulkan/vk_storage_buffer.cc +++ b/source/blender/gpu/vulkan/vk_storage_buffer.cc @@ -23,7 +23,11 @@ void VKStorageBuffer::update(const void *data) void VKStorageBuffer::allocate(VKContext &context) { - buffer_.create(context, size_in_bytes_, usage_, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + buffer_.create(context, + size_in_bytes_, + usage_, + static_cast(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT)); } void VKStorageBuffer::bind(int slot) @@ -43,8 +47,13 @@ void VKStorageBuffer::unbind() { } -void VKStorageBuffer::clear(uint32_t /*clear_value*/) +void VKStorageBuffer::clear(uint32_t clear_value) { + VKContext &context = *VKContext::get(); + if (!buffer_.is_allocated()) { + allocate(context); + } + buffer_.clear(context, clear_value); } void VKStorageBuffer::copy_sub(VertBuf * /*src*/,