diff options
| author | 2022-12-06 13:45:26 +0800 | |
|---|---|---|
| committer | 2022-12-08 10:12:19 +0800 | |
| commit | bf0b957c05013f33855e67c31a48e61b1e86d356 (patch) | |
| tree | 72db2458cb7e5b7572b53527e0755d4fe45e9db0 /src/video_core/engines | |
| parent | Merge pull request #9381 from liamwhite/uninit (diff) | |
| download | yuzu-bf0b957c05013f33855e67c31a48e61b1e86d356.tar.gz yuzu-bf0b957c05013f33855e67c31a48e61b1e86d356.tar.xz yuzu-bf0b957c05013f33855e67c31a48e61b1e86d356.zip | |
video_core: Implement maxwell3d draw manager and split draw logic
Diffstat (limited to 'src/video_core/engines')
| -rw-r--r-- | src/video_core/engines/draw_manager.cpp | 191 | ||||
| -rw-r--r-- | src/video_core/engines/draw_manager.h | 69 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 171 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 25 |
4 files changed, 275 insertions, 181 deletions
diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp new file mode 100644 index 000000000..c59524e58 --- /dev/null +++ b/src/video_core/engines/draw_manager.cpp | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "video_core/dirty_flags.h" | ||
| 5 | #include "video_core/engines/draw_manager.h" | ||
| 6 | #include "video_core/rasterizer_interface.h" | ||
| 7 | |||
| 8 | namespace Tegra::Engines { | ||
| 9 | DrawManager::DrawManager(Maxwell3D* maxwell3d_) : maxwell3d(maxwell3d_) {} | ||
| 10 | |||
| 11 | void DrawManager::ProcessMethodCall(u32 method, u32 argument) { | ||
| 12 | const auto& regs{maxwell3d->regs}; | ||
| 13 | switch (method) { | ||
| 14 | case MAXWELL3D_REG_INDEX(clear_surface): | ||
| 15 | return Clear(1); | ||
| 16 | case MAXWELL3D_REG_INDEX(draw.begin): | ||
| 17 | return DrawBegin(); | ||
| 18 | case MAXWELL3D_REG_INDEX(draw.end): | ||
| 19 | return DrawEnd(); | ||
| 20 | case MAXWELL3D_REG_INDEX(vertex_buffer.first): | ||
| 21 | case MAXWELL3D_REG_INDEX(vertex_buffer.count): | ||
| 22 | case MAXWELL3D_REG_INDEX(index_buffer.first): | ||
| 23 | break; | ||
| 24 | case MAXWELL3D_REG_INDEX(index_buffer.count): | ||
| 25 | draw_state.draw_indexed = true; | ||
| 26 | break; | ||
| 27 | case MAXWELL3D_REG_INDEX(index_buffer32_subsequent): | ||
| 28 | case MAXWELL3D_REG_INDEX(index_buffer16_subsequent): | ||
| 29 | case MAXWELL3D_REG_INDEX(index_buffer8_subsequent): | ||
| 30 | draw_state.instance_count++; | ||
| 31 | [[fallthrough]]; | ||
| 32 | case MAXWELL3D_REG_INDEX(index_buffer32_first): | ||
| 33 | case MAXWELL3D_REG_INDEX(index_buffer16_first): | ||
| 34 | case MAXWELL3D_REG_INDEX(index_buffer8_first): | ||
| 35 | return DrawIndexSmall(argument); | ||
| 36 | case MAXWELL3D_REG_INDEX(draw_inline_index): | ||
| 37 | SetInlineIndexBuffer(argument); | ||
| 38 | break; | ||
| 39 | case MAXWELL3D_REG_INDEX(inline_index_2x16.even): | ||
| 40 | SetInlineIndexBuffer(regs.inline_index_2x16.even); | ||
| 41 | SetInlineIndexBuffer(regs.inline_index_2x16.odd); | ||
| 42 | break; | ||
| 43 | case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): | ||
| 44 | SetInlineIndexBuffer(regs.inline_index_4x8.index0); | ||
| 45 | SetInlineIndexBuffer(regs.inline_index_4x8.index1); | ||
| 46 | SetInlineIndexBuffer(regs.inline_index_4x8.index2); | ||
| 47 | SetInlineIndexBuffer(regs.inline_index_4x8.index3); | ||
| 48 | break; | ||
| 49 | case MAXWELL3D_REG_INDEX(topology_override): | ||
| 50 | use_topology_override = true; | ||
| 51 | break; | ||
| 52 | default: | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | void DrawManager::Clear(u32 layer_count) { | ||
| 58 | maxwell3d->rasterizer->Clear(layer_count); | ||
| 59 | } | ||
| 60 | |||
| 61 | void DrawManager::DrawDeferred() { | ||
| 62 | if (draw_state.draw_mode != DrawMode::Instance || draw_state.instance_count == 0) | ||
| 63 | return; | ||
| 64 | DrawEnd(draw_state.instance_count + 1, true); | ||
| 65 | draw_state.instance_count = 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | void DrawManager::DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, | ||
| 69 | u32 base_instance, u32 num_instances) { | ||
| 70 | draw_state.topology = topology; | ||
| 71 | draw_state.vertex_buffer.first = vertex_first; | ||
| 72 | draw_state.vertex_buffer.count = vertex_count; | ||
| 73 | draw_state.base_instance = base_instance; | ||
| 74 | ProcessDraw(false, num_instances); | ||
| 75 | } | ||
| 76 | |||
| 77 | void DrawManager::DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, | ||
| 78 | u32 base_index, u32 base_instance, u32 num_instances) { | ||
| 79 | const auto& regs{maxwell3d->regs}; | ||
| 80 | draw_state.topology = topology; | ||
| 81 | draw_state.index_buffer = regs.index_buffer; | ||
| 82 | draw_state.index_buffer.first = index_first; | ||
| 83 | draw_state.index_buffer.count = index_count; | ||
| 84 | draw_state.base_index = base_index; | ||
| 85 | draw_state.base_instance = base_instance; | ||
| 86 | ProcessDraw(true, num_instances); | ||
| 87 | } | ||
| 88 | |||
| 89 | void DrawManager::SetInlineIndexBuffer(u32 index) { | ||
| 90 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff)); | ||
| 91 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8)); | ||
| 92 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16)); | ||
| 93 | draw_state.inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); | ||
| 94 | draw_state.draw_mode = DrawMode::InlineIndex; | ||
| 95 | } | ||
| 96 | |||
| 97 | void DrawManager::DrawBegin() { | ||
| 98 | const auto& regs{maxwell3d->regs}; | ||
| 99 | auto reset_instance_count = regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First; | ||
| 100 | auto increment_instance_count = | ||
| 101 | regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent; | ||
| 102 | if (reset_instance_count) { | ||
| 103 | DrawDeferred(); | ||
| 104 | draw_state.instance_count = 0; | ||
| 105 | draw_state.draw_mode = DrawMode::General; | ||
| 106 | } else if (increment_instance_count) { | ||
| 107 | draw_state.instance_count++; | ||
| 108 | draw_state.draw_mode = DrawMode::Instance; | ||
| 109 | } | ||
| 110 | |||
| 111 | draw_state.topology = regs.draw.topology; | ||
| 112 | } | ||
| 113 | |||
| 114 | void DrawManager::DrawEnd(u32 instance_count, bool force_draw) { | ||
| 115 | const auto& regs{maxwell3d->regs}; | ||
| 116 | switch (draw_state.draw_mode) { | ||
| 117 | case DrawMode::Instance: | ||
| 118 | if (!force_draw) | ||
| 119 | break; | ||
| 120 | [[fallthrough]]; | ||
| 121 | case DrawMode::General: | ||
| 122 | draw_state.base_instance = regs.global_base_instance_index; | ||
| 123 | draw_state.base_index = regs.global_base_vertex_index; | ||
| 124 | if (draw_state.draw_indexed) { | ||
| 125 | draw_state.index_buffer = regs.index_buffer; | ||
| 126 | ProcessDraw(true, instance_count); | ||
| 127 | } else { | ||
| 128 | draw_state.vertex_buffer = regs.vertex_buffer; | ||
| 129 | ProcessDraw(false, instance_count); | ||
| 130 | } | ||
| 131 | draw_state.draw_indexed = false; | ||
| 132 | break; | ||
| 133 | case DrawMode::InlineIndex: | ||
| 134 | draw_state.base_instance = regs.global_base_instance_index; | ||
| 135 | draw_state.base_index = regs.global_base_vertex_index; | ||
| 136 | draw_state.index_buffer = regs.index_buffer; | ||
| 137 | draw_state.index_buffer.count = | ||
| 138 | static_cast<u32>(draw_state.inline_index_draw_indexes.size() / 4); | ||
| 139 | draw_state.index_buffer.format = Maxwell3D::Regs::IndexFormat::UnsignedInt; | ||
| 140 | ProcessDraw(true, instance_count); | ||
| 141 | draw_state.inline_index_draw_indexes.clear(); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | void DrawManager::DrawIndexSmall(u32 argument) { | ||
| 147 | const auto& regs{maxwell3d->regs}; | ||
| 148 | IndexBufferSmall index_small_params{argument}; | ||
| 149 | draw_state.base_instance = regs.global_base_instance_index; | ||
| 150 | draw_state.base_index = regs.global_base_vertex_index; | ||
| 151 | draw_state.index_buffer = regs.index_buffer; | ||
| 152 | draw_state.index_buffer.first = index_small_params.first; | ||
| 153 | draw_state.index_buffer.count = index_small_params.count; | ||
| 154 | draw_state.topology = index_small_params.topology; | ||
| 155 | maxwell3d->dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 156 | ProcessDraw(true, 1); | ||
| 157 | } | ||
| 158 | |||
| 159 | void DrawManager::ProcessTopologyOverride() { | ||
| 160 | if (!use_topology_override) | ||
| 161 | return; | ||
| 162 | |||
| 163 | const auto& regs{maxwell3d->regs}; | ||
| 164 | switch (regs.topology_override) { | ||
| 165 | case PrimitiveTopologyOverride::None: | ||
| 166 | break; | ||
| 167 | case PrimitiveTopologyOverride::Points: | ||
| 168 | draw_state.topology = PrimitiveTopology::Points; | ||
| 169 | break; | ||
| 170 | case PrimitiveTopologyOverride::Lines: | ||
| 171 | draw_state.topology = PrimitiveTopology::Lines; | ||
| 172 | break; | ||
| 173 | case PrimitiveTopologyOverride::LineStrip: | ||
| 174 | draw_state.topology = PrimitiveTopology::LineStrip; | ||
| 175 | break; | ||
| 176 | default: | ||
| 177 | draw_state.topology = static_cast<PrimitiveTopology>(regs.topology_override); | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | void DrawManager::ProcessDraw(bool draw_indexed, u32 instance_count) { | ||
| 183 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", draw_state.topology.Value(), | ||
| 184 | draw_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count); | ||
| 185 | |||
| 186 | ProcessTopologyOverride(); | ||
| 187 | |||
| 188 | if (maxwell3d->ShouldExecute()) | ||
| 189 | maxwell3d->rasterizer->Draw(draw_indexed, instance_count); | ||
| 190 | } | ||
| 191 | } // namespace Tegra::Engines | ||
diff --git a/src/video_core/engines/draw_manager.h b/src/video_core/engines/draw_manager.h new file mode 100644 index 000000000..4f67027ca --- /dev/null +++ b/src/video_core/engines/draw_manager.h | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "video_core/engines/maxwell_3d.h" | ||
| 7 | |||
| 8 | namespace VideoCore { | ||
| 9 | class RasterizerInterface; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Tegra::Engines { | ||
| 13 | using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology; | ||
| 14 | using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride; | ||
| 15 | using IndexBuffer = Maxwell3D::Regs::IndexBuffer; | ||
| 16 | using VertexBuffer = Maxwell3D::Regs::VertexBuffer; | ||
| 17 | using IndexBufferSmall = Maxwell3D::Regs::IndexBufferSmall; | ||
| 18 | |||
| 19 | class DrawManager { | ||
| 20 | public: | ||
| 21 | enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; | ||
| 22 | struct State { | ||
| 23 | PrimitiveTopology topology{}; | ||
| 24 | DrawMode draw_mode{}; | ||
| 25 | bool draw_indexed{}; | ||
| 26 | u32 base_index{}; | ||
| 27 | VertexBuffer vertex_buffer; | ||
| 28 | IndexBuffer index_buffer; | ||
| 29 | u32 base_instance{}; | ||
| 30 | u32 instance_count{}; | ||
| 31 | std::vector<u8> inline_index_draw_indexes; | ||
| 32 | }; | ||
| 33 | |||
| 34 | explicit DrawManager(Maxwell3D* maxwell_3d); | ||
| 35 | |||
| 36 | void ProcessMethodCall(u32 method, u32 argument); | ||
| 37 | |||
| 38 | void Clear(u32 layer_count); | ||
| 39 | |||
| 40 | void DrawDeferred(); | ||
| 41 | |||
| 42 | void DrawArray(PrimitiveTopology topology, u32 vertex_first, u32 vertex_count, | ||
| 43 | u32 base_instance, u32 num_instances); | ||
| 44 | |||
| 45 | void DrawIndex(PrimitiveTopology topology, u32 index_first, u32 index_count, u32 base_index, | ||
| 46 | u32 base_instance, u32 num_instances); | ||
| 47 | |||
| 48 | const State& GetDrawState() const { | ||
| 49 | return draw_state; | ||
| 50 | } | ||
| 51 | |||
| 52 | private: | ||
| 53 | void SetInlineIndexBuffer(u32 index); | ||
| 54 | |||
| 55 | void DrawBegin(); | ||
| 56 | |||
| 57 | void DrawEnd(u32 instance_count = 1, bool force_draw = false); | ||
| 58 | |||
| 59 | void DrawIndexSmall(u32 argument); | ||
| 60 | |||
| 61 | void ProcessTopologyOverride(); | ||
| 62 | |||
| 63 | void ProcessDraw(bool draw_indexed, u32 instance_count); | ||
| 64 | |||
| 65 | Maxwell3D* maxwell3d{}; | ||
| 66 | State draw_state{}; | ||
| 67 | bool use_topology_override{}; | ||
| 68 | }; | ||
| 69 | } // namespace Tegra::Engines | ||
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 34bbc72cf..d4ef8d7c5 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "video_core/dirty_flags.h" | 9 | #include "video_core/dirty_flags.h" |
| 10 | #include "video_core/engines/draw_manager.h" | ||
| 10 | #include "video_core/engines/maxwell_3d.h" | 11 | #include "video_core/engines/maxwell_3d.h" |
| 11 | #include "video_core/gpu.h" | 12 | #include "video_core/gpu.h" |
| 12 | #include "video_core/memory_manager.h" | 13 | #include "video_core/memory_manager.h" |
| @@ -21,8 +22,10 @@ using VideoCore::QueryType; | |||
| 21 | constexpr u32 MacroRegistersStart = 0xE00; | 22 | constexpr u32 MacroRegistersStart = 0xE00; |
| 22 | 23 | ||
| 23 | Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) | 24 | Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) |
| 24 | : system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)}, | 25 | : draw_manager{std::make_unique<DrawManager>(this)}, system{system_}, |
| 25 | upload_state{memory_manager, regs.upload} { | 26 | memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)}, upload_state{ |
| 27 | memory_manager, | ||
| 28 | regs.upload} { | ||
| 26 | dirty.flags.flip(); | 29 | dirty.flags.flip(); |
| 27 | InitializeRegisterDefaults(); | 30 | InitializeRegisterDefaults(); |
| 28 | } | 31 | } |
| @@ -116,16 +119,6 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 116 | regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill; | 119 | regs.polygon_mode_front = Maxwell3D::Regs::PolygonMode::Fill; |
| 117 | 120 | ||
| 118 | shadow_state = regs; | 121 | shadow_state = regs; |
| 119 | |||
| 120 | draw_command[MAXWELL3D_REG_INDEX(draw.end)] = true; | ||
| 121 | draw_command[MAXWELL3D_REG_INDEX(draw.begin)] = true; | ||
| 122 | draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.first)] = true; | ||
| 123 | draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; | ||
| 124 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true; | ||
| 125 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; | ||
| 126 | draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; | ||
| 127 | draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; | ||
| 128 | draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; | ||
| 129 | } | 122 | } |
| 130 | 123 | ||
| 131 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { | 124 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { |
| @@ -213,29 +206,6 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 213 | return ProcessCBBind(3); | 206 | return ProcessCBBind(3); |
| 214 | case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): | 207 | case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): |
| 215 | return ProcessCBBind(4); | 208 | return ProcessCBBind(4); |
| 216 | case MAXWELL3D_REG_INDEX(index_buffer32_first): | ||
| 217 | regs.index_buffer.count = regs.index_buffer32_first.count; | ||
| 218 | regs.index_buffer.first = regs.index_buffer32_first.first; | ||
| 219 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 220 | draw_indexed = true; | ||
| 221 | return ProcessDraw(); | ||
| 222 | case MAXWELL3D_REG_INDEX(index_buffer16_first): | ||
| 223 | regs.index_buffer.count = regs.index_buffer16_first.count; | ||
| 224 | regs.index_buffer.first = regs.index_buffer16_first.first; | ||
| 225 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 226 | draw_indexed = true; | ||
| 227 | return ProcessDraw(); | ||
| 228 | case MAXWELL3D_REG_INDEX(index_buffer8_first): | ||
| 229 | regs.index_buffer.count = regs.index_buffer8_first.count; | ||
| 230 | regs.index_buffer.first = regs.index_buffer8_first.first; | ||
| 231 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 232 | draw_indexed = true; | ||
| 233 | return ProcessDraw(); | ||
| 234 | case MAXWELL3D_REG_INDEX(topology_override): | ||
| 235 | use_topology_override = true; | ||
| 236 | return; | ||
| 237 | case MAXWELL3D_REG_INDEX(clear_surface): | ||
| 238 | return ProcessClearBuffers(1); | ||
| 239 | case MAXWELL3D_REG_INDEX(report_semaphore.query): | 209 | case MAXWELL3D_REG_INDEX(report_semaphore.query): |
| 240 | return ProcessQueryGet(); | 210 | return ProcessQueryGet(); |
| 241 | case MAXWELL3D_REG_INDEX(render_enable.mode): | 211 | case MAXWELL3D_REG_INDEX(render_enable.mode): |
| @@ -254,6 +224,9 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 254 | return rasterizer->FragmentBarrier(); | 224 | return rasterizer->FragmentBarrier(); |
| 255 | case MAXWELL3D_REG_INDEX(tiled_cache_barrier): | 225 | case MAXWELL3D_REG_INDEX(tiled_cache_barrier): |
| 256 | return rasterizer->TiledCacheBarrier(); | 226 | return rasterizer->TiledCacheBarrier(); |
| 227 | default: | ||
| 228 | draw_manager->ProcessMethodCall(method, argument); | ||
| 229 | break; | ||
| 257 | } | 230 | } |
| 258 | } | 231 | } |
| 259 | 232 | ||
| @@ -268,7 +241,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) | |||
| 268 | // Execute the current macro. | 241 | // Execute the current macro. |
| 269 | macro_engine->Execute(macro_positions[entry], parameters); | 242 | macro_engine->Execute(macro_positions[entry], parameters); |
| 270 | 243 | ||
| 271 | ProcessDeferredDraw(); | 244 | draw_manager->DrawDeferred(); |
| 272 | } | 245 | } |
| 273 | 246 | ||
| 274 | void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 247 | void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| @@ -291,62 +264,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 291 | const u32 argument = ProcessShadowRam(method, method_argument); | 264 | const u32 argument = ProcessShadowRam(method, method_argument); |
| 292 | ProcessDirtyRegisters(method, argument); | 265 | ProcessDirtyRegisters(method, argument); |
| 293 | 266 | ||
| 294 | if (draw_command[method]) { | 267 | ProcessMethodCall(method, argument, method_argument, is_last_call); |
| 295 | regs.reg_array[method] = method_argument; | ||
| 296 | deferred_draw_method.push_back(method); | ||
| 297 | auto update_inline_index = [&](const u32 index) { | ||
| 298 | inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff)); | ||
| 299 | inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8)); | ||
| 300 | inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16)); | ||
| 301 | inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); | ||
| 302 | draw_mode = DrawMode::InlineIndex; | ||
| 303 | }; | ||
| 304 | switch (method) { | ||
| 305 | case MAXWELL3D_REG_INDEX(draw.begin): { | ||
| 306 | draw_mode = | ||
| 307 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || | ||
| 308 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) | ||
| 309 | ? DrawMode::Instance | ||
| 310 | : DrawMode::General; | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | case MAXWELL3D_REG_INDEX(draw.end): | ||
| 314 | switch (draw_mode) { | ||
| 315 | case DrawMode::General: | ||
| 316 | ProcessDraw(); | ||
| 317 | break; | ||
| 318 | case DrawMode::InlineIndex: | ||
| 319 | regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); | ||
| 320 | regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; | ||
| 321 | draw_indexed = true; | ||
| 322 | ProcessDraw(); | ||
| 323 | inline_index_draw_indexes.clear(); | ||
| 324 | break; | ||
| 325 | case DrawMode::Instance: | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | break; | ||
| 329 | case MAXWELL3D_REG_INDEX(index_buffer.count): | ||
| 330 | draw_indexed = true; | ||
| 331 | break; | ||
| 332 | case MAXWELL3D_REG_INDEX(draw_inline_index): | ||
| 333 | update_inline_index(method_argument); | ||
| 334 | break; | ||
| 335 | case MAXWELL3D_REG_INDEX(inline_index_2x16.even): | ||
| 336 | update_inline_index(regs.inline_index_2x16.even); | ||
| 337 | update_inline_index(regs.inline_index_2x16.odd); | ||
| 338 | break; | ||
| 339 | case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): | ||
| 340 | update_inline_index(regs.inline_index_4x8.index0); | ||
| 341 | update_inline_index(regs.inline_index_4x8.index1); | ||
| 342 | update_inline_index(regs.inline_index_4x8.index2); | ||
| 343 | update_inline_index(regs.inline_index_4x8.index3); | ||
| 344 | break; | ||
| 345 | } | ||
| 346 | } else { | ||
| 347 | ProcessDeferredDraw(); | ||
| 348 | ProcessMethodCall(method, argument, method_argument, is_last_call); | ||
| 349 | } | ||
| 350 | } | 268 | } |
| 351 | 269 | ||
| 352 | void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | 270 | void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, |
| @@ -387,35 +305,6 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, | |||
| 387 | } | 305 | } |
| 388 | } | 306 | } |
| 389 | 307 | ||
| 390 | void Maxwell3D::ProcessTopologyOverride() { | ||
| 391 | using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology; | ||
| 392 | using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride; | ||
| 393 | |||
| 394 | PrimitiveTopology topology{}; | ||
| 395 | |||
| 396 | switch (regs.topology_override) { | ||
| 397 | case PrimitiveTopologyOverride::None: | ||
| 398 | topology = regs.draw.topology; | ||
| 399 | break; | ||
| 400 | case PrimitiveTopologyOverride::Points: | ||
| 401 | topology = PrimitiveTopology::Points; | ||
| 402 | break; | ||
| 403 | case PrimitiveTopologyOverride::Lines: | ||
| 404 | topology = PrimitiveTopology::Lines; | ||
| 405 | break; | ||
| 406 | case PrimitiveTopologyOverride::LineStrip: | ||
| 407 | topology = PrimitiveTopology::LineStrip; | ||
| 408 | break; | ||
| 409 | default: | ||
| 410 | topology = static_cast<PrimitiveTopology>(regs.topology_override); | ||
| 411 | break; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (use_topology_override) { | ||
| 415 | regs.draw.topology.Assign(topology); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | void Maxwell3D::ProcessMacroUpload(u32 data) { | 308 | void Maxwell3D::ProcessMacroUpload(u32 data) { |
| 420 | macro_engine->AddCode(regs.load_mme.instruction_ptr++, data); | 309 | macro_engine->AddCode(regs.load_mme.instruction_ptr++, data); |
| 421 | } | 310 | } |
| @@ -625,44 +514,4 @@ u32 Maxwell3D::GetRegisterValue(u32 method) const { | |||
| 625 | return regs.reg_array[method]; | 514 | return regs.reg_array[method]; |
| 626 | } | 515 | } |
| 627 | 516 | ||
| 628 | void Maxwell3D::ProcessClearBuffers(u32 layer_count) { | ||
| 629 | rasterizer->Clear(layer_count); | ||
| 630 | } | ||
| 631 | |||
| 632 | void Maxwell3D::ProcessDraw(u32 instance_count) { | ||
| 633 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), | ||
| 634 | draw_indexed ? regs.index_buffer.count : regs.vertex_buffer.count); | ||
| 635 | |||
| 636 | ProcessTopologyOverride(); | ||
| 637 | |||
| 638 | if (ShouldExecute()) { | ||
| 639 | rasterizer->Draw(draw_indexed, instance_count); | ||
| 640 | } | ||
| 641 | |||
| 642 | draw_indexed = false; | ||
| 643 | deferred_draw_method.clear(); | ||
| 644 | } | ||
| 645 | |||
| 646 | void Maxwell3D::ProcessDeferredDraw() { | ||
| 647 | if (draw_mode != DrawMode::Instance || deferred_draw_method.empty()) { | ||
| 648 | return; | ||
| 649 | } | ||
| 650 | |||
| 651 | const auto method_count = deferred_draw_method.size(); | ||
| 652 | u32 instance_count = 1; | ||
| 653 | u32 vertex_buffer_count = 0; | ||
| 654 | u32 index_buffer_count = 0; | ||
| 655 | for (size_t index = 0; index < method_count; ++index) { | ||
| 656 | const u32 method = deferred_draw_method[index]; | ||
| 657 | if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) { | ||
| 658 | instance_count = ++vertex_buffer_count; | ||
| 659 | } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) { | ||
| 660 | instance_count = ++index_buffer_count; | ||
| 661 | } | ||
| 662 | } | ||
| 663 | ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?"); | ||
| 664 | |||
| 665 | ProcessDraw(instance_count); | ||
| 666 | } | ||
| 667 | |||
| 668 | } // namespace Tegra::Engines | 517 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index a541cd95f..22b904319 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -37,6 +37,8 @@ class RasterizerInterface; | |||
| 37 | 37 | ||
| 38 | namespace Tegra::Engines { | 38 | namespace Tegra::Engines { |
| 39 | 39 | ||
| 40 | class DrawManager; | ||
| 41 | |||
| 40 | /** | 42 | /** |
| 41 | * This Engine is known as GF100_3D. Documentation can be found in: | 43 | * This Engine is known as GF100_3D. Documentation can be found in: |
| 42 | * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h | 44 | * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/3d/clb197.h |
| @@ -2223,6 +2225,7 @@ public: | |||
| 2223 | 2225 | ||
| 2224 | struct IndexBufferSmall { | 2226 | struct IndexBufferSmall { |
| 2225 | union { | 2227 | union { |
| 2228 | u32 raw; | ||
| 2226 | BitField<0, 16, u32> first; | 2229 | BitField<0, 16, u32> first; |
| 2227 | BitField<16, 12, u32> count; | 2230 | BitField<16, 12, u32> count; |
| 2228 | BitField<28, 4, PrimitiveTopology> topology; | 2231 | BitField<28, 4, PrimitiveTopology> topology; |
| @@ -3061,10 +3064,8 @@ public: | |||
| 3061 | Tables tables{}; | 3064 | Tables tables{}; |
| 3062 | } dirty; | 3065 | } dirty; |
| 3063 | 3066 | ||
| 3064 | std::vector<u8> inline_index_draw_indexes; | 3067 | std::unique_ptr<DrawManager> draw_manager; |
| 3065 | 3068 | friend class DrawManager; | |
| 3066 | /// Handles a write to the CLEAR_BUFFERS register. | ||
| 3067 | void ProcessClearBuffers(u32 layer_count); | ||
| 3068 | 3069 | ||
| 3069 | private: | 3070 | private: |
| 3070 | void InitializeRegisterDefaults(); | 3071 | void InitializeRegisterDefaults(); |
| @@ -3122,15 +3123,6 @@ private: | |||
| 3122 | /// Handles a write to the CB_BIND register. | 3123 | /// Handles a write to the CB_BIND register. |
| 3123 | void ProcessCBBind(size_t stage_index); | 3124 | void ProcessCBBind(size_t stage_index); |
| 3124 | 3125 | ||
| 3125 | /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) | ||
| 3126 | void ProcessTopologyOverride(); | ||
| 3127 | |||
| 3128 | /// Handles deferred draw(e.g., instance draw). | ||
| 3129 | void ProcessDeferredDraw(); | ||
| 3130 | |||
| 3131 | /// Handles a draw. | ||
| 3132 | void ProcessDraw(u32 instance_count = 1); | ||
| 3133 | |||
| 3134 | /// Returns a query's value or an empty object if the value will be deferred through a cache. | 3126 | /// Returns a query's value or an empty object if the value will be deferred through a cache. |
| 3135 | std::optional<u64> GetQueryResult(); | 3127 | std::optional<u64> GetQueryResult(); |
| 3136 | 3128 | ||
| @@ -3153,13 +3145,6 @@ private: | |||
| 3153 | Upload::State upload_state; | 3145 | Upload::State upload_state; |
| 3154 | 3146 | ||
| 3155 | bool execute_on{true}; | 3147 | bool execute_on{true}; |
| 3156 | bool use_topology_override{false}; | ||
| 3157 | |||
| 3158 | std::array<bool, Regs::NUM_REGS> draw_command{}; | ||
| 3159 | std::vector<u32> deferred_draw_method; | ||
| 3160 | enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; | ||
| 3161 | DrawMode draw_mode{DrawMode::General}; | ||
| 3162 | bool draw_indexed{}; | ||
| 3163 | }; | 3148 | }; |
| 3164 | 3149 | ||
| 3165 | #define ASSERT_REG_POSITION(field_name, position) \ | 3150 | #define ASSERT_REG_POSITION(field_name, position) \ |