diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-04-28 17:44:51 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-04-28 17:44:51 +0200 |
| commit | 77decca678b99b388ddbde3517cb9bd5f065cb80 (patch) | |
| tree | 9b427872ec0c7e88cde507e64699f121f86dc2a9 /src/video_core/engines/draw_manager.cpp | |
| parent | ed225f8a8b37a061eeb8e4e69858230b89c6ae50 (diff) | |
[video_core/engines/maxwell3d] memory inline DrawState to reduce indirection on hot paths (#3758)
usual indirection removal
helps very slightly to codegen
the idea is basically to reduce the amount of pointer deference overall in the code, and use idiomatic std::variant<>-isms to not rely on vtables/unique_ptr overhead
this should allow the compiler to emit better code
of course it's a tiny optimisation and only CPU side, but allows us to reduce indirection which is almost always a good thing
"but youre passing more parameters to the function!!!" its literally memoized into a register my friend
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3758
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src/video_core/engines/draw_manager.cpp')
| -rw-r--r-- | src/video_core/engines/draw_manager.cpp | 246 |
1 files changed, 105 insertions, 141 deletions
diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp index 971025cb55..079c7bdc09 100644 --- a/src/video_core/engines/draw_manager.cpp +++ b/src/video_core/engines/draw_manager.cpp @@ -1,23 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/settings.h" #include "video_core/dirty_flags.h" -#include "video_core/engines/draw_manager.h" +#include "video_core/engines/maxwell_3d.h" #include "video_core/rasterizer_interface.h" namespace Tegra::Engines { -DrawManager::DrawManager(Maxwell3D* maxwell3d_) : maxwell3d(maxwell3d_) {} -void DrawManager::ProcessMethodCall(u32 method, u32 argument) { - const auto& regs{maxwell3d->regs}; +void Maxwell3D::DrawManager::ProcessMethodCall(Maxwell3D& maxwell3d, u32 method, u32 argument) { switch (method) { case MAXWELL3D_REG_INDEX(clear_surface): - return Clear(1); + return Clear(maxwell3d, 1); case MAXWELL3D_REG_INDEX(draw.begin): - return DrawBegin(); + return DrawBegin(maxwell3d); case MAXWELL3D_REG_INDEX(draw.end): - return DrawEnd(); + return DrawEnd(maxwell3d); case MAXWELL3D_REG_INDEX(vertex_buffer.first): case MAXWELL3D_REG_INDEX(vertex_buffer.count): case MAXWELL3D_REG_INDEX(index_buffer.first): @@ -33,33 +34,29 @@ void DrawManager::ProcessMethodCall(u32 method, u32 argument) { case MAXWELL3D_REG_INDEX(index_buffer32_first): case MAXWELL3D_REG_INDEX(index_buffer16_first): case MAXWELL3D_REG_INDEX(index_buffer8_first): - return DrawIndexSmall(argument); + return DrawIndexSmall(maxwell3d, argument); case MAXWELL3D_REG_INDEX(draw_inline_index): - SetInlineIndexBuffer(argument); + SetInlineIndexBuffer(maxwell3d, argument); break; case MAXWELL3D_REG_INDEX(inline_index_2x16.even): - SetInlineIndexBuffer(regs.inline_index_2x16.even); - SetInlineIndexBuffer(regs.inline_index_2x16.odd); + SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_2x16.even); + SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_2x16.odd); break; case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): - SetInlineIndexBuffer(regs.inline_index_4x8.index0); - SetInlineIndexBuffer(regs.inline_index_4x8.index1); - SetInlineIndexBuffer(regs.inline_index_4x8.index2); - SetInlineIndexBuffer(regs.inline_index_4x8.index3); + SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index0); + SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index1); + SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index2); + SetInlineIndexBuffer(maxwell3d, maxwell3d.regs.inline_index_4x8.index3); break; case MAXWELL3D_REG_INDEX(vertex_array_instance_first): - DrawArrayInstanced(regs.vertex_array_instance_first.topology.Value(), - regs.vertex_array_instance_first.start.Value(), - regs.vertex_array_instance_first.count.Value(), false); + DrawArrayInstanced(maxwell3d, maxwell3d.regs.vertex_array_instance_first.topology.Value(), maxwell3d.regs.vertex_array_instance_first.start.Value(), maxwell3d.regs.vertex_array_instance_first.count.Value(), false); break; case MAXWELL3D_REG_INDEX(vertex_array_instance_subsequent): { - DrawArrayInstanced(regs.vertex_array_instance_subsequent.topology.Value(), - regs.vertex_array_instance_subsequent.start.Value(), - regs.vertex_array_instance_subsequent.count.Value(), true); + DrawArrayInstanced(maxwell3d, maxwell3d.regs.vertex_array_instance_subsequent.topology.Value(), maxwell3d.regs.vertex_array_instance_subsequent.start.Value(), maxwell3d.regs.vertex_array_instance_subsequent.count.Value(), true); break; } case MAXWELL3D_REG_INDEX(draw_texture.src_y0): { - DrawTexture(); + DrawTexture(maxwell3d); break; } default: @@ -67,101 +64,87 @@ void DrawManager::ProcessMethodCall(u32 method, u32 argument) { } } -void DrawManager::Clear(u32 layer_count) { - if (maxwell3d->ShouldExecute()) { - maxwell3d->rasterizer->Clear(layer_count); +void Maxwell3D::DrawManager::Clear(Maxwell3D& maxwell3d, u32 layer_count) { + if (maxwell3d.ShouldExecute()) { + maxwell3d.rasterizer->Clear(layer_count); } } -void DrawManager::DrawDeferred() { +void Maxwell3D::DrawManager::DrawDeferred(Maxwell3D& maxwell3d) { if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) { return; } - DrawEnd(draw_state.instance_count + 1, true); + DrawEnd(maxwell3d, draw_state.instance_count + 1, true); draw_state.instance_count = 0; } -void DrawManager::DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, - u32 base_instance, u32 num_instances) { +void Maxwell3D::DrawManager::DrawArray(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, u32 base_instance, u32 num_instances) { draw_state.topology = topology; draw_state.vertex_buffer.first = vertex_first; draw_state.vertex_buffer.count = vertex_count; draw_state.base_instance = base_instance; - ProcessDraw(false, num_instances); + ProcessDraw(maxwell3d, false, num_instances); } -void DrawManager::DrawArrayInstanced(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, - bool subsequent) { +void Maxwell3D::DrawManager::DrawArrayInstanced(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, bool subsequent) { draw_state.topology = topology; draw_state.vertex_buffer.first = vertex_first; draw_state.vertex_buffer.count = vertex_count; - if (!subsequent) { draw_state.instance_count = 1; } - draw_state.base_instance = draw_state.instance_count - 1; draw_state.draw_mode = DrawMode::Instance; draw_state.instance_count++; - ProcessDraw(false, 1); + ProcessDraw(maxwell3d, false, 1); } -void DrawManager::DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, - u32 base_index, u32 base_instance, u32 num_instances) { - const auto& regs{maxwell3d->regs}; +void Maxwell3D::DrawManager::DrawIndex(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, u32 base_instance, u32 num_instances) { draw_state.topology = topology; - draw_state.index_buffer = regs.index_buffer; + draw_state.index_buffer = maxwell3d.regs.index_buffer; draw_state.index_buffer.first = index_first; draw_state.index_buffer.count = index_count; draw_state.base_index = base_index; draw_state.base_instance = base_instance; - ProcessDraw(true, num_instances); + ProcessDraw(maxwell3d, true, num_instances); } -void DrawManager::DrawArrayIndirect(PrimitiveTopology topology) { +void Maxwell3D::DrawManager::DrawArrayIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology) { draw_state.topology = topology; - - ProcessDrawIndirect(); + ProcessDrawIndirect(maxwell3d); } -void DrawManager::DrawIndexedIndirect(PrimitiveTopology topology, u32 index_first, - u32 index_count) { - const auto& regs{maxwell3d->regs}; +void Maxwell3D::DrawManager::DrawIndexedIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count) { draw_state.topology = topology; - draw_state.index_buffer = regs.index_buffer; + draw_state.index_buffer = maxwell3d.regs.index_buffer; draw_state.index_buffer.first = index_first; draw_state.index_buffer.count = index_count; - - ProcessDrawIndirect(); + ProcessDrawIndirect(maxwell3d); } -void DrawManager::SetInlineIndexBuffer(u32 index) { - draw_state.inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff)); - draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8)); - draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16)); - draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); +void Maxwell3D::DrawManager::SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 index) { + draw_state.inline_index_draw_indexes.push_back(u8(index & 0x000000ff)); + draw_state.inline_index_draw_indexes.push_back(u8((index & 0x0000ff00) >> 8)); + draw_state.inline_index_draw_indexes.push_back(u8((index & 0x00ff0000) >> 16)); + draw_state.inline_index_draw_indexes.push_back(u8((index & 0xff000000) >> 24)); draw_state.draw_mode = DrawMode::InlineIndex; } -void DrawManager::DrawBegin() { - const auto& regs{maxwell3d->regs}; - auto reset_instance_count = regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First; - auto increment_instance_count = - regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent; +void Maxwell3D::DrawManager::DrawBegin(Maxwell3D& maxwell3d) { + auto reset_instance_count = maxwell3d.regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First; + auto increment_instance_count = maxwell3d.regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent; if (reset_instance_count) { - DrawDeferred(); + DrawDeferred(maxwell3d); draw_state.instance_count = 0; draw_state.draw_mode = DrawMode::General; } else if (increment_instance_count) { draw_state.instance_count++; draw_state.draw_mode = DrawMode::Instance; } - - draw_state.topology = regs.draw.topology; + draw_state.topology = maxwell3d.regs.draw.topology; } -void DrawManager::DrawEnd(u32 instance_count, bool force_draw) { - const auto& regs{maxwell3d->regs}; +void Maxwell3D::DrawManager::DrawEnd(Maxwell3D& maxwell3d, u32 instance_count, bool force_draw) { switch (draw_state.draw_mode) { case DrawMode::Instance: if (!force_draw) { @@ -169,119 +152,100 @@ void DrawManager::DrawEnd(u32 instance_count, bool force_draw) { } [[fallthrough]]; case DrawMode::General: - draw_state.base_instance = regs.global_base_instance_index; - draw_state.base_index = regs.global_base_vertex_index; + draw_state.base_instance = maxwell3d.regs.global_base_instance_index; + draw_state.base_index = maxwell3d.regs.global_base_vertex_index; if (draw_state.draw_indexed) { - draw_state.index_buffer = regs.index_buffer; - ProcessDraw(true, instance_count); + draw_state.index_buffer = maxwell3d.regs.index_buffer; + ProcessDraw(maxwell3d, true, instance_count); } else { - draw_state.vertex_buffer = regs.vertex_buffer; - ProcessDraw(false, instance_count); + draw_state.vertex_buffer = maxwell3d.regs.vertex_buffer; + ProcessDraw(maxwell3d, false, instance_count); } draw_state.draw_indexed = false; break; case DrawMode::InlineIndex: - draw_state.base_instance = regs.global_base_instance_index; - draw_state.base_index = regs.global_base_vertex_index; - draw_state.index_buffer = regs.index_buffer; - draw_state.index_buffer.count = - static_cast<u32>(draw_state.inline_index_draw_indexes.size() / 4); + draw_state.base_instance = maxwell3d.regs.global_base_instance_index; + draw_state.base_index = maxwell3d.regs.global_base_vertex_index; + draw_state.index_buffer = maxwell3d.regs.index_buffer; + draw_state.index_buffer.count = u32(draw_state.inline_index_draw_indexes.size() / 4); draw_state.index_buffer.format = Maxwell3D::Regs::IndexFormat::UnsignedInt; - maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; - ProcessDraw(true, instance_count); + maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; + ProcessDraw(maxwell3d, true, instance_count); draw_state.inline_index_draw_indexes.clear(); break; } } -void DrawManager::DrawIndexSmall(u32 argument) { - const auto& regs{maxwell3d->regs}; - IndexBufferSmall index_small_params{argument}; - draw_state.base_instance = regs.global_base_instance_index; - draw_state.base_index = regs.global_base_vertex_index; - draw_state.index_buffer = regs.index_buffer; +void Maxwell3D::DrawManager::DrawIndexSmall(Maxwell3D& maxwell3d, u32 argument) { + Maxwell3D::Regs::IndexBufferSmall index_small_params{argument}; + draw_state.base_instance = maxwell3d.regs.global_base_instance_index; + draw_state.base_index = maxwell3d.regs.global_base_vertex_index; + draw_state.index_buffer = maxwell3d.regs.index_buffer; draw_state.index_buffer.first = index_small_params.first; draw_state.index_buffer.count = index_small_params.count; draw_state.topology = index_small_params.topology; - maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; - ProcessDraw(true, 1); + maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; + ProcessDraw(maxwell3d, true, 1); } -void DrawManager::DrawTexture() { - const auto& regs{maxwell3d->regs}; - draw_texture_state.dst_x0 = static_cast<float>(regs.draw_texture.dst_x0) / 4096.f; - draw_texture_state.dst_y0 = static_cast<float>(regs.draw_texture.dst_y0) / 4096.f; - const auto dst_width = static_cast<float>(regs.draw_texture.dst_width) / 4096.f; - const auto dst_height = static_cast<float>(regs.draw_texture.dst_height) / 4096.f; - const bool lower_left{regs.window_origin.mode != - Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft}; +void Maxwell3D::DrawManager::DrawTexture(Maxwell3D& maxwell3d) { + draw_texture_state.dst_x0 = f32(maxwell3d.regs.draw_texture.dst_x0) / 4096.f; + draw_texture_state.dst_y0 = f32(maxwell3d.regs.draw_texture.dst_y0) / 4096.f; + const auto dst_width = f32(maxwell3d.regs.draw_texture.dst_width) / 4096.f; + const auto dst_height = f32(maxwell3d.regs.draw_texture.dst_height) / 4096.f; + const bool lower_left{maxwell3d.regs.window_origin.mode != Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft}; if (lower_left) { - draw_texture_state.dst_y0 = - static_cast<f32>(regs.surface_clip.height) - draw_texture_state.dst_y0; + draw_texture_state.dst_y0 = f32(maxwell3d.regs.surface_clip.height) - draw_texture_state.dst_y0; } draw_texture_state.dst_x1 = draw_texture_state.dst_x0 + dst_width; draw_texture_state.dst_y1 = draw_texture_state.dst_y0 + dst_height; - draw_texture_state.src_x0 = static_cast<float>(regs.draw_texture.src_x0) / 4096.f; - draw_texture_state.src_y0 = static_cast<float>(regs.draw_texture.src_y0) / 4096.f; - draw_texture_state.src_x1 = - (static_cast<float>(regs.draw_texture.dx_du) / 4294967296.f) * dst_width + - draw_texture_state.src_x0; - draw_texture_state.src_y1 = - (static_cast<float>(regs.draw_texture.dy_dv) / 4294967296.f) * dst_height + - draw_texture_state.src_y0; - draw_texture_state.src_sampler = regs.draw_texture.src_sampler; - draw_texture_state.src_texture = regs.draw_texture.src_texture; - maxwell3d->rasterizer->DrawTexture(); -} - -void DrawManager::UpdateTopology() { - const auto& regs{maxwell3d->regs}; - switch (regs.primitive_topology_control) { - case PrimitiveTopologyControl::UseInBeginMethods: + draw_texture_state.src_x0 = f32(maxwell3d.regs.draw_texture.src_x0) / 4096.f; + draw_texture_state.src_y0 = f32(maxwell3d.regs.draw_texture.src_y0) / 4096.f; + draw_texture_state.src_x1 = (f32(maxwell3d.regs.draw_texture.dx_du) / 4294967296.f) * dst_width + draw_texture_state.src_x0; + draw_texture_state.src_y1 = (f32(maxwell3d.regs.draw_texture.dy_dv) / 4294967296.f) * dst_height + draw_texture_state.src_y0; + draw_texture_state.src_sampler = maxwell3d.regs.draw_texture.src_sampler; + draw_texture_state.src_texture = maxwell3d.regs.draw_texture.src_texture; + maxwell3d.rasterizer->DrawTexture(); +} + +void Maxwell3D::DrawManager::UpdateTopology(Maxwell3D& maxwell3d) { + switch (maxwell3d.regs.primitive_topology_control) { + case Maxwell3D::Regs::PrimitiveTopologyControl::UseInBeginMethods: break; - case PrimitiveTopologyControl::UseSeparateState: - switch (regs.topology_override) { - case PrimitiveTopologyOverride::None: + case Maxwell3D::Regs::PrimitiveTopologyControl::UseSeparateState: + switch (maxwell3d.regs.topology_override) { + case Maxwell3D::Regs::PrimitiveTopologyOverride::None: break; - case PrimitiveTopologyOverride::Points: - draw_state.topology = PrimitiveTopology::Points; + case Maxwell3D::Regs::PrimitiveTopologyOverride::Points: + draw_state.topology = Maxwell3D::Regs::PrimitiveTopology::Points; break; - case PrimitiveTopologyOverride::Lines: - draw_state.topology = PrimitiveTopology::Lines; + case Maxwell3D::Regs::PrimitiveTopologyOverride::Lines: + draw_state.topology = Maxwell3D::Regs::PrimitiveTopology::Lines; break; - case PrimitiveTopologyOverride::LineStrip: - draw_state.topology = PrimitiveTopology::LineStrip; + case Maxwell3D::Regs::PrimitiveTopologyOverride::LineStrip: + draw_state.topology = Maxwell3D::Regs::PrimitiveTopology::LineStrip; break; default: - draw_state.topology = static_cast<PrimitiveTopology>(regs.topology_override); + draw_state.topology = Maxwell3D::Regs::PrimitiveTopology(maxwell3d.regs.topology_override); break; } break; } } -void DrawManager::ProcessDraw(bool draw_indexed, u32 instance_count) { - LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology, - draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count); - - UpdateTopology(); - - if (maxwell3d->ShouldExecute()) { - maxwell3d->rasterizer->Draw(draw_indexed, instance_count); +void Maxwell3D::DrawManager::ProcessDraw(Maxwell3D& maxwell3d, bool draw_indexed, u32 instance_count) { + LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology, draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count); + UpdateTopology(maxwell3d); + if (maxwell3d.ShouldExecute()) { + maxwell3d.rasterizer->Draw(draw_indexed, instance_count); } } -void DrawManager::ProcessDrawIndirect() { - LOG_TRACE( - HW_GPU, - "called, topology={}, is_indexed={}, includes_count={}, buffer_size={}, max_draw_count={}", - draw_state.topology, indirect_state.is_indexed, indirect_state.include_count, - indirect_state.buffer_size, indirect_state.max_draw_counts); - - UpdateTopology(); - - if (maxwell3d->ShouldExecute()) { - maxwell3d->rasterizer->DrawIndirect(); +void Maxwell3D::DrawManager::ProcessDrawIndirect(Maxwell3D& maxwell3d) { + LOG_TRACE(HW_GPU, "called, topology={}, is_indexed={}, includes_count={}, buffer_size={}, max_draw_count={}", draw_state.topology, indirect_state.is_indexed, indirect_state.include_count, indirect_state.buffer_size, indirect_state.max_draw_counts); + UpdateTopology(maxwell3d); + if (maxwell3d.ShouldExecute()) { + maxwell3d.rasterizer->DrawIndirect(); } } } // namespace Tegra::Engines |
