diff options
Diffstat (limited to 'src/video_core/engines/maxwell_3d.cpp')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 6adfcf89b8..92313988bd 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -164,6 +164,8 @@ bool Maxwell3D::IsMethodExecutable(u32 method) { case MAXWELL3D_REG_INDEX(vertex_array_instance_first): case MAXWELL3D_REG_INDEX(vertex_array_instance_subsequent): case MAXWELL3D_REG_INDEX(draw_texture.src_y0): + case RootTables::SelectMethod: + case RootTables::LoadMethod: case MAXWELL3D_REG_INDEX(wait_for_idle): case MAXWELL3D_REG_INDEX(shadow_ram_control): case MAXWELL3D_REG_INDEX(load_mme.instruction_ptr): @@ -336,6 +338,12 @@ void Maxwell3D::ConsumeSinkImpl(Core::System& system) { } void Maxwell3D::ProcessDirtyRegisters(u32 method, u32 argument) { + // The instances after the first are drawn together once their loop ends, and they must see + // the state they were begun with: NVN's draw macros reset the base instance (and its copy in + // c[0][0x644]) right after the loop, before the macro returns. + if (draw_manager.HasDeferredDraw() && !DrawManager::IsInstanceLoopMethod(method)) [[unlikely]] { + draw_manager.DrawDeferred(*this, true); + } regs.reg_array[method] = argument; for (auto const& table : dirty.tables) dirty.flags[table[method]] = true; @@ -346,6 +354,17 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume LOG_DEBUG(HW_GPU, "Native GPU surface clear: value={:#x}", argument); } switch (method) { + case RootTables::SelectMethod: + root_tables.selected = argument & 7; + root_tables.offset = (argument >> 8) & 0xff; + return; + case RootTables::LoadMethod: + if (root_tables.offset < 256 && root_tables.offset % 4 == 0) { + root_tables.tables[root_tables.selected][root_tables.offset / 4] = argument; + root_tables.loaded = true; + } + root_tables.offset += 4; + return; case MAXWELL3D_REG_INDEX(wait_for_idle): return rasterizer->WaitForIdle(); case MAXWELL3D_REG_INDEX(shadow_ram_control): @@ -499,6 +518,10 @@ void Maxwell3D::DumpRecentWrites(u32 method) { } LOG_ERROR(HW_GPU, "Write to {:#x} while macro {:#x} collects parameters ({} so far); last writes:", method, executing_macro, macro_params.size()); + if (!record_write_history) { + LOG_ERROR(HW_GPU, "Register write history disabled; EDEN_NX2_3D_HISTORY=1 enables it"); + return; + } for (size_t i = 0; i < recent_writes.size(); ++i) { const auto& w = recent_writes[(recent_write_index + i) % recent_writes.size()]; if (w.amount != 0) { @@ -516,6 +539,10 @@ void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* bas ProcessMacro(system, method, base_start, amount, amount == methods_pending); return; } + // As in ProcessDirtyRegisters: the paths below write without it. + if (draw_manager.HasDeferredDraw() && !DrawManager::IsInstanceLoopMethod(method)) [[unlikely]] { + draw_manager.DrawDeferred(*this, true); + } switch (method) { case MAXWELL3D_REG_INDEX(const_buffer.buffer): case MAXWELL3D_REG_INDEX(const_buffer.buffer) + 1: @@ -795,7 +822,6 @@ struct Maxwell3D::FrontState { Regs::ShadowRamControl control{}; u32 executing_macro{}; std::vector<u32> parameters; - std::vector<u32> fifo; u64 calls{}; /// A method the draw manager handles was sent since the back last ran DrawDeferred: only /// then can it have a deferred instanced draw to issue at the end of a macro. @@ -819,6 +845,8 @@ bool FrontHandledOutsideDrawManager(u32 method) { return true; } switch (method) { + case Maxwell3D::RootTables::SelectMethod: + case Maxwell3D::RootTables::LoadMethod: case MAXWELL3D_REG_INDEX(wait_for_idle): case MAXWELL3D_REG_INDEX(shadow_ram_control): case MAXWELL3D_REG_INDEX(load_mme.instruction_ptr): @@ -1070,9 +1098,9 @@ void Maxwell3D::FrontRunMacro(Core::System& system, VideoCommon::GpuSplit& split engine.native_jit = std::make_shared<TuringMacroJit>(); } engine.native_jit->Prepare(engine.native_code, engine.native_code_generation); - fs.fifo.assign(fs.parameters.begin(), fs.parameters.end()); + const size_t parameter_count = fs.parameters.size(); const auto result = engine.native_jit->Execute( - start, fs.fifo, std::span<u32>{native_data_ram}, + start, fs.parameters, std::span<u32>{native_data_ram}, [&fs](u32 address) { return address < Regs::NUM_REGS ? fs.regs[address] : 0U; }, [&](u32 address, u32 value) { if (address >= MacroRegistersStart) { @@ -1088,7 +1116,7 @@ void Maxwell3D::FrontRunMacro(Core::System& system, VideoCommon::GpuSplit& split if (!result.success) { engine.native_execution_failed = true; LOG_ERROR(HW_GPU, "Native MME (JIT, split front) failed: start={:#x}, consumed={}/{}, error={}", - start, result.consumed, fs.parameters.size(), result.error); + start, result.consumed, parameter_count, result.error); } } fs.parameters.clear(); @@ -1123,7 +1151,7 @@ void Maxwell3D::FrontDmaRead(VideoCommon::GpuSplit& split, FrontState& fs, u32 m for (u32 i = 0; i < words; ++i) { const u32 word = memory_manager.Read<u32>(source + u64{i} * sizeof(u32)); if (method == 0x158) { - fs.fifo.push_back(word); + fs.parameters.push_back(word); } else if (ram + i < native_data_ram.size()) { native_data_ram[ram + i] = word; } |
