diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index b61a574f58..4dd800b941 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -352,7 +352,8 @@ void BufferCache

::UpdateComputeBuffers() { } template -void BufferCache

::BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_vertex_input) { +void BufferCache

::BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_vertex_input, + vk::CommandBuffer* cmd) { if (is_indexed) { BindHostIndexBuffer(); } else if constexpr (!HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { @@ -363,7 +364,7 @@ void BufferCache

::BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_v draw_state.vertex_buffer.count); } } - BindHostVertexBuffers(use_dynamic_vertex_input); + BindHostVertexBuffers(use_dynamic_vertex_input, cmd); BindHostTransformFeedbackBuffers(); if (current_draw_indirect) { BindHostDrawIndirectBuffers(); @@ -764,7 +765,7 @@ void BufferCache

::BindHostIndexBuffer() { } template -void BufferCache

::BindHostVertexBuffers(bool use_dynamic_vertex_input) { +void BufferCache

::BindHostVertexBuffers(bool use_dynamic_vertex_input, vk::CommandBuffer* cmd) { HostBindings host_bindings; bool any_valid{false}; auto& flags = maxwell3d->dirty.flags; @@ -800,7 +801,7 @@ void BufferCache

::BindHostVertexBuffers(bool use_dynamic_vertex_input) { host_bindings.sizes.push_back(binding.size); host_bindings.strides.push_back(stride); } - runtime.BindVertexBuffers(host_bindings, use_dynamic_vertex_input); + runtime.BindVertexBuffers(host_bindings, use_dynamic_vertex_input, cmd); } } diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 925b83dff9..da5b9f3301 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -38,6 +38,10 @@ namespace VideoCommon { +namespace vk { + class CommandBuffer; +} + using BufferId = Common::SlotId; using VideoCore::Surface::PixelFormat; @@ -232,7 +236,8 @@ public: void UpdateComputeBuffers(); - void BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_vertex_input = false); + void BindHostGeometryBuffers(bool is_indexed, bool use_dynamic_vertex_input = false, + vk::CommandBuffer* cmd = nullptr); void BindHostStageBuffers(size_t stage); @@ -358,7 +363,7 @@ private: void BindHostIndexBuffer(); - void BindHostVertexBuffers(bool use_dynamic_vertex_input = false); + void BindHostVertexBuffers(bool use_dynamic_vertex_input = false, vk::CommandBuffer* cmd = nullptr); void BindHostDrawIndirectBuffers(); diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index bba04c6b5e..9b6c2ab718 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -552,31 +552,42 @@ void BufferCacheRuntime::BindQuadIndexBuffer(PrimitiveTopology topology, u32 fir } void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride, - bool use_dynamic_vertex_input) { + bool use_dynamic_vertex_input, vk::CommandBuffer* cmd) { if (index >= device.GetMaxVertexInputBindings()) { return; } if (use_dynamic_vertex_input && device.IsExtExtendedDynamicStateSupported()) { - scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { + if (cmd) { const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0; const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE; const VkDeviceSize vk_stride = stride; - cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); - }); + cmd->BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); + } else { + scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { + const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0; + const VkDeviceSize vk_size = buffer != VK_NULL_HANDLE ? size : VK_WHOLE_SIZE; + const VkDeviceSize vk_stride = stride; + cmdbuf.BindVertexBuffers2EXT(index, 1, &buffer, &vk_offset, &vk_size, &vk_stride); + }); + } } else { if (!device.HasNullDescriptor() && buffer == VK_NULL_HANDLE) { ReserveNullBuffer(); buffer = *null_buffer; offset = 0; } - scheduler.Record([index, buffer, offset](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffer(index, buffer, offset); - }); + if (cmd) { + cmd->BindVertexBuffer(index, buffer, offset); + } else { + scheduler.Record([index, buffer, offset](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffer(index, buffer, offset); + }); + } } } void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings, - bool use_dynamic_vertex_input) { + bool use_dynamic_vertex_input, vk::CommandBuffer* cmd) { boost::container::small_vector buffer_handles; for (u32 index = 0; index < bindings.buffers.size(); ++index) { auto handle = bindings.buffers[index]->Handle(); @@ -598,20 +609,31 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bi return; } if (use_dynamic_vertex_input && device.IsExtExtendedDynamicStateSupported()) { - scheduler.Record([bindings_ = std::move(bindings), - buffer_handles_ = std::move(buffer_handles), - binding_count](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, binding_count, buffer_handles_.data(), - bindings_.offsets.data(), bindings_.sizes.data(), - bindings_.strides.data()); - }); + if (cmd) { + cmd->BindVertexBuffers2EXT(bindings.min_index, binding_count, buffer_handles.data(), + bindings.offsets.data(), bindings.sizes.data(), + bindings.strides.data()); + } else { + scheduler.Record([ + bindings_ = std::move(bindings), buffer_handles_ = std::move(buffer_handles), + binding_count](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, binding_count, + buffer_handles_.data(), bindings_.offsets.data(), + bindings_.sizes.data(), bindings_.strides.data()); + }); + } } else { - scheduler.Record([bindings_ = std::move(bindings), - buffer_handles_ = std::move(buffer_handles), - binding_count](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffers(bindings_.min_index, binding_count, buffer_handles_.data(), - bindings_.offsets.data()); - }); + if (cmd) { + cmd->BindVertexBuffers(bindings.min_index, binding_count, buffer_handles.data(), + bindings.offsets.data()); + } else { + scheduler.Record([ + bindings_ = std::move(bindings), buffer_handles_ = std::move(buffer_handles), + binding_count](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffers(bindings_.min_index, binding_count, + buffer_handles_.data(), bindings_.offsets.data()); + }); + } } } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 7bcfb8d72f..8bd4493b13 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -124,10 +124,10 @@ public: void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count); void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride, - bool use_dynamic_vertex_input); + bool use_dynamic_vertex_input, vk::CommandBuffer* cmd = nullptr); void BindVertexBuffers(VideoCommon::HostBindings& bindings, - bool use_dynamic_vertex_input); + bool use_dynamic_vertex_input, vk::CommandBuffer* cmd = nullptr); void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9e94689f23..922b233c6b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -225,7 +225,10 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { UpdateDynamicStates(); - pipeline->SetPreBindCallback([this](vk::CommandBuffer cmdbuf) { RecordDynamicStates(cmdbuf); }); + pipeline->SetPreBindCallback([this, is_indexed, pipeline](vk::CommandBuffer cmdbuf) { + RecordDynamicStates(cmdbuf); + buffer_cache.BindHostGeometryBuffers(is_indexed, pipeline->HasDynamicVertexInput(), &cmdbuf); + }); SCOPE_EXIT { pipeline->ClearPreBindCallback(); }; if (!pipeline->Configure(is_indexed))