Fix: Vulkan Multi Indirect Drawing

Multi indirect drawing would bind an offset index buffer, but
indirect drawing parameters also offset the index buffer so
incorrect geometry was drawn.

Fixes drawing of meshes with multiple materials.

Pull Request: https://projects.blender.org/blender/blender/pulls/115190
This commit is contained in:
Jeroen Bakker 2023-11-20 15:48:06 +01:00
parent 07b5e1bd80
commit d638357d6f
5 changed files with 10 additions and 18 deletions

View File

@ -78,7 +78,8 @@ void VKBatch::multi_draw_indirect(GPUStorageBuf *indirect_buf,
VKStorageBuffer &indirect_buffer = *unwrap(unwrap(indirect_buf));
VKContext &context = *VKContext::get();
const bool draw_indexed = index_buffer_get() != nullptr;
VKIndexBuffer *index_buffer = index_buffer_get();
const bool draw_indexed = index_buffer != nullptr;
VKCommandBuffers &command_buffers = context.command_buffers_get();
if (draw_indexed) {
command_buffers.draw_indexed_indirect(indirect_buffer, offset, count, stride);

View File

@ -293,16 +293,14 @@ void VKCommandBuffers::bind(const uint32_t binding,
command_buffer.command_recorded();
}
void VKCommandBuffers::bind(const VKBufferWithOffset &index_buffer, VkIndexType index_type)
void VKCommandBuffers::bind(const VKBuffer &index_buffer, VkIndexType index_type)
{
VKCommandBuffer &command_buffer = command_buffer_get(Type::Graphics);
validate_framebuffer_exists();
ensure_active_framebuffer();
vkCmdBindIndexBuffer(command_buffer.vk_command_buffer(),
index_buffer.buffer.vk_handle(),
index_buffer.offset,
index_type);
vkCmdBindIndexBuffer(
command_buffer.vk_command_buffer(), index_buffer.vk_handle(), 0, index_type);
command_buffer.command_recorded();
}

View File

@ -76,7 +76,7 @@ class VKCommandBuffers : public NonCopyable, NonMovable {
void bind(const uint32_t binding, const VKBufferWithOffset &vertex_buffer);
void bind(const uint32_t binding, const VkBuffer &vk_vertex_buffer, const VkDeviceSize offset);
/* Bind the given buffer as an index buffer. */
void bind(const VKBufferWithOffset &index_buffer, VkIndexType index_type);
void bind(const VKBuffer &index_buffer, VkIndexType index_type);
void begin_render_pass(VKFrameBuffer &framebuffer);
void end_render_pass(const VKFrameBuffer &framebuffer);

View File

@ -37,7 +37,7 @@ void VKIndexBuffer::upload_data()
void VKIndexBuffer::bind(VKContext &context)
{
context.command_buffers_get().bind(buffer_with_offset(), to_vk_index_type(index_type_));
context.command_buffers_get().bind(buffer_get(), to_vk_index_type(index_type_));
}
void VKIndexBuffer::bind_as_ssbo(uint binding)
@ -88,16 +88,9 @@ void VKIndexBuffer::allocate()
debug::object_label(buffer_.vk_handle(), "IndexBuffer");
}
VKBufferWithOffset VKIndexBuffer::buffer_with_offset()
VKBuffer &VKIndexBuffer::buffer_get()
{
VKIndexBuffer *src = unwrap(src_);
VKBufferWithOffset result{is_subrange_ ? src->buffer_ : buffer_, index_start_};
BLI_assert_msg(is_subrange_ || result.offset == 0,
"According to design index_start should always be zero when index buffer isn't "
"a subrange");
return result;
return is_subrange_ ? unwrap(src_)->buffer_ : buffer_;
}
} // namespace blender::gpu

View File

@ -40,7 +40,7 @@ class VKIndexBuffer : public IndexBuf, public VKBindableResource {
void strip_restart_indices() override;
void allocate();
void ensure_updated();
VKBufferWithOffset buffer_with_offset();
VKBuffer &buffer_get();
};
static inline VKIndexBuffer *unwrap(IndexBuf *index_buffer)