diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index 92d77eef2d..69633de5c9 100644 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h @@ -289,6 +289,11 @@ public: return cpu_addr; } + /// Update the base CPU address of the buffer + void UpdateCpuAddr(VAddr cpu_addr_) noexcept { + cpu_addr = cpu_addr_; + } + /// Returns the offset relative to the given CPU address /// @pre IsInBounds returns true [[nodiscard]] u32 Offset(VAddr other_cpu_addr) const noexcept { diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 627917ab6c..468dbfd9e2 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -205,9 +205,9 @@ public: current_draw_indirect = current_draw_indirect_; } - [[nodiscard]] std::pair GetDrawIndirectCount(); + [[nodiscard]] typename BufferCache

::Buffer* GetDrawIndirectCount(); - [[nodiscard]] std::pair GetDrawIndirectBuffer(); + [[nodiscard]] typename BufferCache

::Buffer* GetDrawIndirectBuffer(); std::recursive_mutex mutex; Runtime& runtime; @@ -385,6 +385,9 @@ private: SlotVector slot_buffers; DelayedDestructionRing delayed_destruction_ring; + Buffer indirect_buffer; + Buffer indirect_count_buffer; + const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{}; u32 last_index_count = 0; @@ -458,7 +461,9 @@ private: template BufferCache

::BufferCache(VideoCore::RasterizerInterface& rasterizer_, Core::Memory::Memory& cpu_memory_, Runtime& runtime_) - : runtime{runtime_}, rasterizer{rasterizer_}, cpu_memory{cpu_memory_} { + : runtime{runtime_}, rasterizer{rasterizer_}, cpu_memory{cpu_memory_}, + indirect_buffer(runtime, rasterizer, 0, 0x1000), + indirect_count_buffer(runtime, rasterizer, 0, 0x1000) { // Ensure the first slot is used for the null buffer void(slot_buffers.insert(runtime, NullBufferParams{})); common_ranges.clear(); @@ -1064,15 +1069,13 @@ void BufferCache

::BindHostVertexBuffers() { template void BufferCache

::BindHostDrawIndirectBuffers() { - const auto bind_buffer = [this](const Binding& binding) { - Buffer& buffer = slot_buffers[binding.buffer_id]; - TouchBuffer(buffer, binding.buffer_id); + const auto bind_buffer = [this](const Binding& binding, Buffer& buffer) { SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); }; if (current_draw_indirect->include_count) { - bind_buffer(count_buffer_binding); + bind_buffer(count_buffer_binding, indirect_count_buffer); } - bind_buffer(indirect_buffer_binding); + bind_buffer(indirect_buffer_binding, indirect_buffer); } template @@ -1409,14 +1412,16 @@ void BufferCache

::UpdateDrawIndirect() { binding = Binding{ .cpu_addr = *cpu_addr, .size = static_cast(size), - .buffer_id = FindBuffer(*cpu_addr, static_cast(size)), + .buffer_id = NULL_BUFFER_ID, }; }; if (current_draw_indirect->include_count) { update(current_draw_indirect->count_start_address, sizeof(u32), count_buffer_binding); + indirect_count_buffer.UpdateCpuAddr(count_buffer_binding.cpu_addr); } update(current_draw_indirect->indirect_start_address, current_draw_indirect->buffer_size, indirect_buffer_binding); + indirect_buffer.UpdateCpuAddr(indirect_buffer_binding.cpu_addr); } template @@ -2007,15 +2012,13 @@ bool BufferCache

::HasFastUniformBufferBound(size_t stage, u32 binding_index) } template -std::pair::Buffer*, u32> BufferCache

::GetDrawIndirectCount() { - auto& buffer = slot_buffers[count_buffer_binding.buffer_id]; - return std::make_pair(&buffer, buffer.Offset(count_buffer_binding.cpu_addr)); +typename BufferCache

::Buffer* BufferCache

::GetDrawIndirectCount() { + return &indirect_count_buffer; } template -std::pair::Buffer*, u32> BufferCache

::GetDrawIndirectBuffer() { - auto& buffer = slot_buffers[indirect_buffer_binding.buffer_id]; - return std::make_pair(&buffer, buffer.Offset(indirect_buffer_binding.cpu_addr)); +typename BufferCache

::Buffer* BufferCache

::GetDrawIndirectBuffer() { + return &indirect_buffer; } } // namespace VideoCommon diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7bced675c7..9744519d3e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -285,23 +285,19 @@ void RasterizerOpenGL::DrawIndirect() { const auto& params = maxwell3d->draw_manager->GetIndirectParams(); buffer_cache.SetDrawIndirect(¶ms); PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { - const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); - const GLvoid* const gl_offset = - reinterpret_cast(static_cast(offset)); + const auto buffer = buffer_cache.GetDrawIndirectBuffer(); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->Handle()); if (params.include_count) { - const auto [draw_buffer, offset_base] = buffer_cache.GetDrawIndirectCount(); + const auto draw_buffer = buffer_cache.GetDrawIndirectCount(); glBindBuffer(GL_PARAMETER_BUFFER, draw_buffer->Handle()); if (params.is_indexed) { const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); - glMultiDrawElementsIndirectCount(primitive_mode, format, gl_offset, - static_cast(offset_base), + glMultiDrawElementsIndirectCount(primitive_mode, format, nullptr, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } else { - glMultiDrawArraysIndirectCount(primitive_mode, gl_offset, - static_cast(offset_base), + glMultiDrawArraysIndirectCount(primitive_mode, nullptr, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } @@ -309,11 +305,11 @@ void RasterizerOpenGL::DrawIndirect() { } if (params.is_indexed) { const GLenum format = MaxwellToGL::IndexFormat(maxwell3d->regs.index_buffer.format); - glMultiDrawElementsIndirect(primitive_mode, format, gl_offset, + glMultiDrawElementsIndirect(primitive_mode, format, nullptr, static_cast(params.max_draw_counts), static_cast(params.stride)); } else { - glMultiDrawArraysIndirect(primitive_mode, gl_offset, + glMultiDrawArraysIndirect(primitive_mode, nullptr, static_cast(params.max_draw_counts), static_cast(params.stride)); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 719edbcfbe..68e9eec169 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -230,35 +230,29 @@ void RasterizerVulkan::DrawIndirect() { const auto& params = maxwell3d->draw_manager->GetIndirectParams(); buffer_cache.SetDrawIndirect(¶ms); PrepareDraw(params.is_indexed, [this, ¶ms] { - const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer(); - const auto& buffer = indirect_buffer.first; - const auto& offset = indirect_buffer.second; + const auto buffer = buffer_cache.GetDrawIndirectBuffer(); if (params.include_count) { - const auto count = buffer_cache.GetDrawIndirectCount(); - const auto& draw_buffer = count.first; - const auto& offset_base = count.second; + const auto draw_buffer = buffer_cache.GetDrawIndirectCount(); scheduler.Record([draw_buffer_obj = draw_buffer->Handle(), - buffer_obj = buffer->Handle(), offset_base, offset, - params](vk::CommandBuffer cmdbuf) { + buffer_obj = buffer->Handle(), params](vk::CommandBuffer cmdbuf) { if (params.is_indexed) { - cmdbuf.DrawIndexedIndirectCount( - buffer_obj, offset, draw_buffer_obj, offset_base, - static_cast(params.max_draw_counts), static_cast(params.stride)); + cmdbuf.DrawIndexedIndirectCount(buffer_obj, 0, draw_buffer_obj, 0, + static_cast(params.max_draw_counts), + static_cast(params.stride)); } else { - cmdbuf.DrawIndirectCount(buffer_obj, offset, draw_buffer_obj, offset_base, + cmdbuf.DrawIndirectCount(buffer_obj, 0, draw_buffer_obj, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } }); return; } - scheduler.Record([buffer_obj = buffer->Handle(), offset, params](vk::CommandBuffer cmdbuf) { + scheduler.Record([buffer_obj = buffer->Handle(), params](vk::CommandBuffer cmdbuf) { if (params.is_indexed) { - cmdbuf.DrawIndexedIndirect(buffer_obj, offset, - static_cast(params.max_draw_counts), + cmdbuf.DrawIndexedIndirect(buffer_obj, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } else { - cmdbuf.DrawIndirect(buffer_obj, offset, static_cast(params.max_draw_counts), + cmdbuf.DrawIndirect(buffer_obj, 0, static_cast(params.max_draw_counts), static_cast(params.stride)); } });