From 70f9d723000733e24407fbe6155e818a0d366978 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 23 May 2023 16:19:13 +0200 Subject: [PATCH 1/2] Vulkan: Add Support For Texture Buffers Texture buffers are vbos that can be sampled as textures inside shaders. This adds support for them to the Vulkan Backend. --- source/blender/gpu/CMakeLists.txt | 2 + .../gpu/shaders/infos/gpu_shader_test_info.hh | 7 ++ .../blender/gpu/tests/buffer_texture_test.cc | 68 +++++++++++++++++++ .../shaders/gpu_buffer_texture_test.glsl | 6 ++ source/blender/gpu/vulkan/vk_backend.cc | 2 + source/blender/gpu/vulkan/vk_batch.cc | 5 +- .../blender/gpu/vulkan/vk_descriptor_set.cc | 29 +++++++- .../blender/gpu/vulkan/vk_descriptor_set.hh | 12 +++- source/blender/gpu/vulkan/vk_immediate.cc | 5 +- source/blender/gpu/vulkan/vk_state_manager.cc | 64 +++++++++++------ source/blender/gpu/vulkan/vk_state_manager.hh | 14 +++- source/blender/gpu/vulkan/vk_texture.cc | 25 ++++++- source/blender/gpu/vulkan/vk_vertex_buffer.cc | 62 +++++++++++++++-- source/blender/gpu/vulkan/vk_vertex_buffer.hh | 13 ++++ 14 files changed, 279 insertions(+), 35 deletions(-) create mode 100644 source/blender/gpu/tests/buffer_texture_test.cc create mode 100644 source/blender/gpu/tests/shaders/gpu_buffer_texture_test.glsl diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index ebbb267f63f..e40ca3c0125 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -566,6 +566,7 @@ set(GLSL_SRC set(GLSL_SRC_TEST tests/shaders/gpu_math_test.glsl + tests/shaders/gpu_buffer_texture_test.glsl tests/shaders/gpu_compute_1d_test.glsl tests/shaders/gpu_compute_2d_test.glsl tests/shaders/gpu_compute_ibo_test.glsl @@ -847,6 +848,7 @@ if(WITH_GTESTS) set(TEST_SRC tests/gpu_testing.cc + tests/buffer_texture_test.cc tests/framebuffer_test.cc tests/immediate_test.cc tests/index_buffer_test.cc diff --git a/source/blender/gpu/shaders/infos/gpu_shader_test_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_test_info.hh index ec7327df214..5798bfbd16f 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_test_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_test_info.hh @@ -85,6 +85,13 @@ GPU_SHADER_CREATE_INFO(gpu_push_constants_512bytes_test) .push_constant(Type::FLOAT, "filler3", 64) .do_static_compilation(true); +GPU_SHADER_CREATE_INFO(gpu_buffer_texture_test) + .local_group_size(1) + .sampler(0, ImageType::FLOAT_BUFFER, "bufferTexture") + .storage_buf(0, Qualifier::WRITE, "float", "data_out[]") + .compute_source("gpu_buffer_texture_test.glsl") + .do_static_compilation(true); + GPU_SHADER_CREATE_INFO(eevee_shadow_test) .fragment_source("eevee_shadow_test.glsl") .additional_info("gpu_shader_test") diff --git a/source/blender/gpu/tests/buffer_texture_test.cc b/source/blender/gpu/tests/buffer_texture_test.cc new file mode 100644 index 00000000000..57acbdde5d7 --- /dev/null +++ b/source/blender/gpu/tests/buffer_texture_test.cc @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "GPU_capabilities.h" +#include "GPU_compute.h" +#include "GPU_vertex_buffer.h" +#include "GPU_vertex_format.h" + +#include "BLI_index_range.hh" +#include "BLI_math_vector_types.hh" + +#include "gpu_testing.hh" + +namespace blender::gpu::tests { + +static constexpr int Size = 256; + +static void test_buffer_texture() +{ + if (!GPU_compute_shader_support() && !GPU_shader_storage_buffer_objects_support()) { + /* We can't test as a the platform does not support compute shaders. */ + std::cout << "Skipping compute shader test: platform not supported"; + GTEST_SKIP(); + } + + /* Build compute shader. */ + GPUShader *shader = GPU_shader_create_from_info_name("gpu_buffer_texture_test"); + EXPECT_NE(shader, nullptr); + GPU_shader_bind(shader); + + /* Vertex buffer. */ + GPUVertFormat format = {}; + uint value_pos = GPU_vertformat_attr_add(&format, "value", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + GPUVertBuf *vertex_buffer = GPU_vertbuf_create_with_format_ex( + &format, GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY); + float4 value = float4(42.42, 23.23, 1.0, -1.0); + GPU_vertbuf_data_alloc(vertex_buffer, 4); + GPU_vertbuf_attr_fill(vertex_buffer, value_pos, &value); + GPU_vertbuf_bind_as_texture(vertex_buffer, + GPU_shader_get_sampler_binding(shader, "bufferTexture")); + + /* Construct SSBO. */ + GPUStorageBuf *ssbo = GPU_storagebuf_create_ex( + 4 * sizeof(float), nullptr, GPU_USAGE_DEVICE_ONLY, __func__); + GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "data_out")); + + /* Dispatch compute task. */ + GPU_compute_dispatch(shader, 4, 1, 1); + + /* Check if compute has been done. */ + GPU_memory_barrier(GPU_BARRIER_BUFFER_UPDATE); + + /* Download the index buffer. */ + float4 read_data; + GPU_storagebuf_read(ssbo, read_data); + EXPECT_EQ(read_data, value); + + /* Cleanup. */ + GPU_shader_unbind(); + GPU_storagebuf_free(ssbo); + GPU_vertbuf_discard(vertex_buffer); + GPU_shader_free(shader); +} + +GPU_TEST(buffer_texture) + +} // namespace blender::gpu::tests diff --git a/source/blender/gpu/tests/shaders/gpu_buffer_texture_test.glsl b/source/blender/gpu/tests/shaders/gpu_buffer_texture_test.glsl new file mode 100644 index 00000000000..4c84812c657 --- /dev/null +++ b/source/blender/gpu/tests/shaders/gpu_buffer_texture_test.glsl @@ -0,0 +1,6 @@ +void main() +{ + int index = int(gl_GlobalInvocationID.x); + float value = texelFetch(bufferTexture, index).r; + data_out[index] = value; +} diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc index a9bd54d310f..499d807b37a 100644 --- a/source/blender/gpu/vulkan/vk_backend.cc +++ b/source/blender/gpu/vulkan/vk_backend.cc @@ -17,6 +17,7 @@ #include "vk_pixel_buffer.hh" #include "vk_query.hh" #include "vk_shader.hh" +#include "vk_state_manager.hh" #include "vk_storage_buffer.hh" #include "vk_texture.hh" #include "vk_uniform_buffer.hh" @@ -64,6 +65,7 @@ void VKBackend::samplers_update() {} void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) { VKContext &context = *VKContext::get(); + context.state_manager_get().apply_bindings(); context.bind_compute_pipeline(); VKCommandBuffer &command_buffer = context.command_buffer_get(); command_buffer.dispatch(groups_x_len, groups_y_len, groups_z_len); diff --git a/source/blender/gpu/vulkan/vk_batch.cc b/source/blender/gpu/vulkan/vk_batch.cc index d1d2997d3d3..63bf1683b8c 100644 --- a/source/blender/gpu/vulkan/vk_batch.cc +++ b/source/blender/gpu/vulkan/vk_batch.cc @@ -9,6 +9,7 @@ #include "vk_context.hh" #include "vk_index_buffer.hh" +#include "vk_state_manager.hh" #include "vk_vertex_attribute_object.hh" #include "vk_vertex_buffer.hh" @@ -22,7 +23,9 @@ void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int i /* Finalize graphics pipeline */ VKContext &context = *VKContext::get(); - context.state_manager->apply_state(); + VKStateManager &state_manager = context.state_manager_get(); + state_manager.apply_state(); + state_manager.apply_bindings(); VKVertexAttributeObject vao; vao.update_bindings(context, *this); context.bind_graphics_pipeline(prim_type, vao); diff --git a/source/blender/gpu/vulkan/vk_descriptor_set.cc b/source/blender/gpu/vulkan/vk_descriptor_set.cc index b9847a74d05..52369302ecd 100644 --- a/source/blender/gpu/vulkan/vk_descriptor_set.cc +++ b/source/blender/gpu/vulkan/vk_descriptor_set.cc @@ -94,6 +94,15 @@ void VKDescriptorSetTracker::bind(VKTexture &texture, binding.vk_sampler = sampler.vk_handle(); } +void VKDescriptorSetTracker::bind(VKVertexBuffer &vertex_buffer, + const VKDescriptorSet::Location location) +{ + Binding &binding = ensure_location(location); + binding.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + binding.vk_buffer_view = vertex_buffer.vk_buffer_view_get(); + binding.buffer_size = vertex_buffer.size_alloc_get(); +} + VKDescriptorSetTracker::Binding &VKDescriptorSetTracker::ensure_location( const VKDescriptorSet::Location location) { @@ -115,8 +124,10 @@ void VKDescriptorSetTracker::update(VKContext &context) tracked_resource_for(context, !bindings_.is_empty()); std::unique_ptr &descriptor_set = active_descriptor_set(); VkDescriptorSet vk_descriptor_set = descriptor_set->vk_handle(); + BLI_assert(vk_descriptor_set != VK_NULL_HANDLE); Vector buffer_infos; + buffer_infos.reserve(16); Vector descriptor_writes; for (const Binding &binding : bindings_) { @@ -138,7 +149,22 @@ void VKDescriptorSetTracker::update(VKContext &context) descriptor_writes.append(write_descriptor); } + for (const Binding &binding : bindings_) { + if (!binding.is_texel_buffer()) { + continue; + } + VkWriteDescriptorSet write_descriptor = {}; + write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptor.dstSet = vk_descriptor_set; + write_descriptor.dstBinding = binding.location; + write_descriptor.descriptorCount = 1; + write_descriptor.descriptorType = binding.type; + write_descriptor.pTexelBufferView = &binding.vk_buffer_view; + descriptor_writes.append(write_descriptor); + } + Vector image_infos; + image_infos.reserve(16); for (const Binding &binding : bindings_) { if (!binding.is_image()) { continue; @@ -161,9 +187,6 @@ void VKDescriptorSetTracker::update(VKContext &context) descriptor_writes.append(write_descriptor); } - BLI_assert_msg(image_infos.size() + buffer_infos.size() == descriptor_writes.size(), - "Not all changes have been converted to a write descriptor. Check " - "`Binding::is_buffer` and `Binding::is_image`."); const VKDevice &device = VKBackend::get().device_get(); vkUpdateDescriptorSets( device.device_get(), descriptor_writes.size(), descriptor_writes.data(), 0, nullptr); diff --git a/source/blender/gpu/vulkan/vk_descriptor_set.hh b/source/blender/gpu/vulkan/vk_descriptor_set.hh index 8f7c984fcd1..c79d8a49eeb 100644 --- a/source/blender/gpu/vulkan/vk_descriptor_set.hh +++ b/source/blender/gpu/vulkan/vk_descriptor_set.hh @@ -83,12 +83,14 @@ class VKDescriptorSet : NonCopyable { VKDescriptorSet(VkDescriptorPool vk_descriptor_pool, VkDescriptorSet vk_descriptor_set) : vk_descriptor_pool_(vk_descriptor_pool), vk_descriptor_set_(vk_descriptor_set) { + BLI_assert(vk_descriptor_set_ != VK_NULL_HANDLE); } VKDescriptorSet(VKDescriptorSet &&other); virtual ~VKDescriptorSet(); VKDescriptorSet &operator=(VKDescriptorSet &&other) { + BLI_assert(other.vk_descriptor_set_ != VK_NULL_HANDLE); vk_descriptor_set_ = other.vk_descriptor_set_; vk_descriptor_pool_ = other.vk_descriptor_pool_; other.mark_freed(); @@ -118,6 +120,8 @@ class VKDescriptorSetTracker : protected VKResourceTracker { VkBuffer vk_buffer = VK_NULL_HANDLE; VkDeviceSize buffer_size = 0; + VkBufferView vk_buffer_view = VK_NULL_HANDLE; + VKTexture *texture = nullptr; VkSampler vk_sampler = VK_NULL_HANDLE; @@ -131,6 +135,11 @@ class VKDescriptorSetTracker : protected VKResourceTracker { return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); } + bool is_texel_buffer() const + { + return ELEM(type, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); + } + bool is_image() const { return ELEM(type, @@ -157,7 +166,8 @@ class VKDescriptorSetTracker : protected VKResourceTracker { /* TODO: bind as image */ void image_bind(VKTexture &texture, VKDescriptorSet::Location location); void bind(VKTexture &texture, VKDescriptorSet::Location location, VKSampler &sampler); - + /* Bind as uniform texel buffer. */ + void bind(VKVertexBuffer &vertex_buffer, VKDescriptorSet::Location location); /** * Some shaders don't need any descriptor sets so we don't need to bind them. * diff --git a/source/blender/gpu/vulkan/vk_immediate.cc b/source/blender/gpu/vulkan/vk_immediate.cc index d5f7d2c1618..8ef30520729 100644 --- a/source/blender/gpu/vulkan/vk_immediate.cc +++ b/source/blender/gpu/vulkan/vk_immediate.cc @@ -9,6 +9,7 @@ #include "vk_immediate.hh" #include "vk_data_conversion.hh" +#include "vk_state_manager.hh" namespace blender::gpu { @@ -47,7 +48,9 @@ void VKImmediate::end() VKContext &context = *VKContext::get(); BLI_assert(context.shader == unwrap(shader)); - context.state_manager->apply_state(); + VKStateManager &state_manager = context.state_manager_get(); + state_manager.apply_state(); + state_manager.apply_bindings(); vertex_attributes_.update_bindings(*this); context.bind_graphics_pipeline(prim_type, vertex_attributes_); vertex_attributes_.bind(context); diff --git a/source/blender/gpu/vulkan/vk_state_manager.cc b/source/blender/gpu/vulkan/vk_state_manager.cc index 5c5b82899d9..059ecc3bb9b 100644 --- a/source/blender/gpu/vulkan/vk_state_manager.cc +++ b/source/blender/gpu/vulkan/vk_state_manager.cc @@ -10,6 +10,7 @@ #include "vk_pipeline.hh" #include "vk_shader.hh" #include "vk_texture.hh" +#include "vk_vertex_buffer.hh" #include "GPU_capabilities.h" @@ -21,8 +22,8 @@ VKStateManager::VKStateManager() constexpr int max_bindings = 16; image_bindings_ = Array(max_bindings); image_bindings_.fill(ImageBinding()); - texture_bindings_ = Array(max_bindings); - texture_bindings_.fill(ImageBinding()); + texture_bindings_ = Array(max_bindings); + texture_bindings_.fill(TextureBinding()); uniform_buffer_bindings_ = Array(max_bindings); uniform_buffer_bindings_.fill(UniformBufferBinding()); } @@ -34,27 +35,33 @@ void VKStateManager::apply_state() VKShader &shader = unwrap(*context.shader); VKPipeline &pipeline = shader.pipeline_get(); pipeline.state_manager_get().set_state(state, mutable_state); + } +} +void VKStateManager::apply_bindings() +{ + VKContext &context = *VKContext::get(); + if (context.shader) { for (int binding : IndexRange(image_bindings_.size())) { - if (image_bindings_[binding].texture == nullptr) { - continue; + if (image_bindings_[binding].texture) { + image_bindings_[binding].texture->image_bind(binding); } - image_bindings_[binding].texture->image_bind(binding); } - for (int binding : IndexRange(image_bindings_.size())) { - if (texture_bindings_[binding].texture == nullptr) { - continue; + for (int binding : IndexRange(texture_bindings_.size())) { + if (texture_bindings_[binding].texture) { + texture_bindings_[binding].texture->bind(binding, sampler_); + } + else if (texture_bindings_[binding].vertex_buffer) { + texture_bindings_[binding].vertex_buffer->bind(binding); } - texture_bindings_[binding].texture->bind(binding, sampler_); } for (int binding : IndexRange(uniform_buffer_bindings_.size())) { - if (uniform_buffer_bindings_[binding].buffer == nullptr) { - continue; + if (uniform_buffer_bindings_[binding].buffer) { + uniform_buffer_bindings_[binding].buffer->bind( + binding, shader::ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER); } - uniform_buffer_bindings_[binding].buffer->bind( - binding, shader::ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER); } } } @@ -81,12 +88,13 @@ void VKStateManager::texture_bind(Texture *tex, GPUSamplerState /*sampler*/, int { VKTexture *texture = unwrap(tex); texture_bindings_[unit].texture = texture; + texture_bindings_[unit].vertex_buffer = nullptr; } void VKStateManager::texture_unbind(Texture *tex) { VKTexture *texture = unwrap(tex); - for (ImageBinding &binding : texture_bindings_) { + for (TextureBinding &binding : texture_bindings_) { if (binding.texture == texture) { binding.texture = nullptr; } @@ -95,10 +103,8 @@ void VKStateManager::texture_unbind(Texture *tex) void VKStateManager::texture_unbind_all() { - for (ImageBinding &binding : texture_bindings_) { - if (binding.texture != nullptr) { - binding.texture = nullptr; - } + for (TextureBinding &binding : texture_bindings_) { + binding.texture = nullptr; } } @@ -120,10 +126,8 @@ void VKStateManager::image_unbind(Texture *tex) void VKStateManager::image_unbind_all() { - for (ImageBinding &binding : texture_bindings_) { - if (binding.texture != nullptr) { - binding.texture = nullptr; - } + for (TextureBinding &binding : texture_bindings_) { + binding.texture = nullptr; } } @@ -141,6 +145,22 @@ void VKStateManager::uniform_buffer_unbind(VKUniformBuffer *uniform_buffer) } } +void VKStateManager::texel_buffer_bind(VKVertexBuffer *vertex_buffer, int slot) +{ + texture_bindings_[slot].vertex_buffer = vertex_buffer; + texture_bindings_[slot].texture = nullptr; +} + +void VKStateManager::texel_buffer_unbind(VKVertexBuffer *vertex_buffer) +{ + for (TextureBinding &binding : texture_bindings_) { + if (binding.vertex_buffer == vertex_buffer) { + binding.vertex_buffer = nullptr; + binding.texture = nullptr; + } + } +} + void VKStateManager::texture_unpack_row_length_set(uint len) { texture_unpack_row_length_ = len; diff --git a/source/blender/gpu/vulkan/vk_state_manager.hh b/source/blender/gpu/vulkan/vk_state_manager.hh index a454d74a7ef..47609f5c03e 100644 --- a/source/blender/gpu/vulkan/vk_state_manager.hh +++ b/source/blender/gpu/vulkan/vk_state_manager.hh @@ -16,6 +16,7 @@ namespace blender::gpu { class VKTexture; class VKUniformBuffer; +class VKVertexBuffer; class VKStateManager : public StateManager { /* Dummy sampler for now.*/ @@ -23,6 +24,11 @@ class VKStateManager : public StateManager { uint texture_unpack_row_length_ = 0; + struct TextureBinding { + VKTexture *texture = nullptr; + /* bufferTextures and samplers share the same namespace. */ + VKVertexBuffer *vertex_buffer = nullptr; + }; struct ImageBinding { VKTexture *texture = nullptr; }; @@ -30,7 +36,7 @@ class VKStateManager : public StateManager { VKUniformBuffer *buffer = nullptr; }; Array image_bindings_; - Array texture_bindings_; + Array texture_bindings_; Array uniform_buffer_bindings_; public: @@ -41,6 +47,9 @@ class VKStateManager : public StateManager { void issue_barrier(eGPUBarrier barrier_bits) override; + /** Apply resources to the bindings of the active shader.*/ + void apply_bindings(); + void texture_bind(Texture *tex, GPUSamplerState sampler, int unit) override; void texture_unbind(Texture *tex) override; void texture_unbind_all() override; @@ -52,6 +61,9 @@ class VKStateManager : public StateManager { void uniform_buffer_bind(VKUniformBuffer *uniform_buffer, int slot); void uniform_buffer_unbind(VKUniformBuffer *uniform_buffer); + void texel_buffer_bind(VKVertexBuffer *vertex_buffer, int slot); + void texel_buffer_unbind(VKVertexBuffer *vertex_buffer); + void texture_unpack_row_length_set(uint len) override; /** diff --git a/source/blender/gpu/vulkan/vk_texture.cc b/source/blender/gpu/vulkan/vk_texture.cc index b1fc27ff209..82ebab7f7dc 100644 --- a/source/blender/gpu/vulkan/vk_texture.cc +++ b/source/blender/gpu/vulkan/vk_texture.cc @@ -14,6 +14,7 @@ #include "vk_shader.hh" #include "vk_shader_interface.hh" #include "vk_state_manager.hh" +#include "vk_vertex_buffer.hh" #include "BLI_math_vector.hh" @@ -174,9 +175,29 @@ bool VKTexture::init_internal() return true; } -bool VKTexture::init_internal(GPUVertBuf * /*vbo*/) +bool VKTexture::init_internal(GPUVertBuf *vbo) { - return false; + if (!allocate()) { + return false; + } + + VKVertexBuffer *vertex_buffer = unwrap(unwrap(vbo)); + + VkBufferImageCopy region = {}; + region.imageExtent.width = w_; + region.imageExtent.height = 1; + region.imageExtent.depth = 1; + region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_); + region.imageSubresource.mipLevel = 0; + region.imageSubresource.layerCount = 1; + + VKContext &context = *VKContext::get(); + layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VKCommandBuffer &command_buffer = context.command_buffer_get(); + command_buffer.copy(*this, vertex_buffer->buffer_, Span(®ion, 1)); + command_buffer.submit(); + + return true; } bool VKTexture::init_internal(GPUTexture * /*src*/, diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.cc b/source/blender/gpu/vulkan/vk_vertex_buffer.cc index 0286b0088c1..b4dc7083fb6 100644 --- a/source/blender/gpu/vulkan/vk_vertex_buffer.cc +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.cc @@ -8,8 +8,10 @@ #include "MEM_guardedalloc.h" #include "vk_data_conversion.hh" +#include "vk_memory.hh" #include "vk_shader.hh" #include "vk_shader_interface.hh" +#include "vk_state_manager.hh" #include "vk_vertex_buffer.hh" namespace blender::gpu { @@ -35,9 +37,44 @@ void VKVertexBuffer::bind_as_ssbo(uint binding) shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, *location); } -void VKVertexBuffer::bind_as_texture(uint /*binding*/) +void VKVertexBuffer::bind_as_texture(uint binding) { - NOT_YET_IMPLEMENTED + VKContext &context = *VKContext::get(); + VKStateManager &state_manager = context.state_manager_get(); + state_manager.texel_buffer_bind(this, binding); + should_unbind_ = true; +} + +void VKVertexBuffer::bind(uint binding) +{ + VKContext &context = *VKContext::get(); + VKShader *shader = static_cast(context.shader); + const VKShaderInterface &shader_interface = shader->interface_get(); + const std::optional location = + shader_interface.descriptor_set_location( + shader::ShaderCreateInfo::Resource::BindType::SAMPLER, binding); + if (!location) { + return; + } + + upload_data(); + + if (vk_buffer_view_ == VK_NULL_HANDLE) { + VkBufferViewCreateInfo buffer_view_info = {}; + eGPUTextureFormat texture_format = to_texture_format(&format); + + buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; + buffer_view_info.buffer = buffer_.vk_handle(); + buffer_view_info.format = to_vk_format(texture_format); + buffer_view_info.range = buffer_.size_in_bytes(); + + VK_ALLOCATION_CALLBACKS; + const VKDevice &device = VKBackend::get().device_get(); + vkCreateBufferView( + device.device_get(), &buffer_view_info, vk_allocation_callbacks, &vk_buffer_view_); + } + + shader->pipeline_get().descriptor_set_get().bind(*this, *location); } void VKVertexBuffer::wrap_handle(uint64_t /*handle*/) @@ -81,6 +118,18 @@ void VKVertexBuffer::resize_data() void VKVertexBuffer::release_data() { + if (should_unbind_) { + VKContext &context = *VKContext::get(); + context.state_manager_get().texel_buffer_unbind(this); + } + + if (vk_buffer_view_ != VK_NULL_HANDLE) { + VK_ALLOCATION_CALLBACKS; + const VKDevice &device = VKBackend::get().device_get(); + vkDestroyBufferView(device.device_get(), vk_buffer_view_, vk_allocation_callbacks); + vk_buffer_view_ = VK_NULL_HANDLE; + } + MEM_SAFE_FREE(data); } @@ -105,6 +154,9 @@ void VKVertexBuffer::upload_data() if (!buffer_.is_allocated()) { allocate(); } + if (!ELEM(usage_, GPU_USAGE_STATIC, GPU_USAGE_STREAM, GPU_USAGE_DYNAMIC)) { + return; + } if (flag & GPU_VERTBUF_DATA_DIRTY) { void *data_to_upload = data; @@ -133,8 +185,10 @@ void VKVertexBuffer::allocate() { buffer_.create(size_alloc_get(), usage_, - static_cast(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); + static_cast(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)); debug::object_label(buffer_.vk_handle(), "VertexBuffer"); } diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.hh b/source/blender/gpu/vulkan/vk_vertex_buffer.hh index 9e653a28b96..c131bcf670a 100644 --- a/source/blender/gpu/vulkan/vk_vertex_buffer.hh +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.hh @@ -15,12 +15,16 @@ namespace blender::gpu { class VKVertexBuffer : public VertBuf { VKBuffer buffer_; + bool should_unbind_ = false; + /** When a vertex buffer is used as a UNIFORM_TEXEL_BUFFER the buffer requires a buffer view. */ + VkBufferView vk_buffer_view_ = VK_NULL_HANDLE; public: ~VKVertexBuffer(); void bind_as_ssbo(uint binding) override; void bind_as_texture(uint binding) override; + void bind(uint binding); void wrap_handle(uint64_t handle) override; void update_sub(uint start, uint len, const void *data) override; @@ -32,6 +36,12 @@ class VKVertexBuffer : public VertBuf { return buffer_.vk_handle(); } + VkBufferView vk_buffer_view_get() const + { + BLI_assert(vk_buffer_view_ != VK_NULL_HANDLE); + return vk_buffer_view_; + } + protected: void acquire_data() override; void resize_data() override; @@ -42,6 +52,9 @@ class VKVertexBuffer : public VertBuf { private: void allocate(); void *convert() const; + + /* VKTexture requires access to `buffer_` to convert a vertex buffer to a texture.*/ + friend class VKTexture; }; static inline VKVertexBuffer *unwrap(VertBuf *vertex_buffer) -- 2.30.2 From a45a95cd2aa659d603c17cdbfc89dd31727885cc Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 23 May 2023 16:23:26 +0200 Subject: [PATCH 2/2] Remove unused code. --- source/blender/gpu/tests/buffer_texture_test.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/gpu/tests/buffer_texture_test.cc b/source/blender/gpu/tests/buffer_texture_test.cc index 57acbdde5d7..66f310dfd01 100644 --- a/source/blender/gpu/tests/buffer_texture_test.cc +++ b/source/blender/gpu/tests/buffer_texture_test.cc @@ -14,8 +14,6 @@ namespace blender::gpu::tests { -static constexpr int Size = 256; - static void test_buffer_texture() { if (!GPU_compute_shader_support() && !GPU_shader_storage_buffer_objects_support()) { -- 2.30.2