mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-06-26 21:09:27 -04:00
[maxwell_3d] append inline index draw streams in bulk (#4083)
Inline index draws arrive as a batch but were processed one word at a time, so each index ran through the full per-method path and got appended a byte at a time. Handle the whole batch in one pass instead, updating state once and appending all the indices together. Replay shadow control still goes word by word since it has to reload each one. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4083 Reviewed-by: Lizzie <lizzie@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
parent
09b6b3b71e
commit
0d6a2158f0
3 changed files with 60 additions and 0 deletions
|
|
@ -4,6 +4,8 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "video_core/dirty_flags.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
|
|
@ -130,6 +132,44 @@ void Maxwell3D::DrawManager::SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 inde
|
|||
draw_state.draw_mode = DrawMode::InlineIndex;
|
||||
}
|
||||
|
||||
void Maxwell3D::DrawManager::SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 method,
|
||||
const u32* base_start, u32 amount) {
|
||||
auto& index_buffer = draw_state.inline_index_draw_indexes;
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(draw_inline_index): {
|
||||
const auto* const bytes = reinterpret_cast<const u8*>(base_start);
|
||||
index_buffer.insert(index_buffer.end(), bytes, bytes + size_t(amount) * sizeof(u32));
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(inline_index_2x16.even): {
|
||||
const size_t offset = index_buffer.size();
|
||||
index_buffer.resize(offset + size_t(amount) * 2 * sizeof(u32));
|
||||
u8* dst = index_buffer.data() + offset;
|
||||
for (u32 i = 0; i < amount; ++i) {
|
||||
const u32 word = base_start[i];
|
||||
const u32 indexes[2]{word & 0xFFFF, word >> 16};
|
||||
std::memcpy(dst, indexes, sizeof(indexes));
|
||||
dst += sizeof(indexes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): {
|
||||
const size_t offset = index_buffer.size();
|
||||
index_buffer.resize(offset + size_t(amount) * 4 * sizeof(u32));
|
||||
u8* dst = index_buffer.data() + offset;
|
||||
for (u32 i = 0; i < amount; ++i) {
|
||||
const u32 word = base_start[i];
|
||||
const u32 indexes[4]{word & 0xFF, (word >> 8) & 0xFF, (word >> 16) & 0xFF,
|
||||
word >> 24};
|
||||
std::memcpy(dst, indexes, sizeof(indexes));
|
||||
dst += sizeof(indexes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
draw_state.draw_mode = DrawMode::InlineIndex;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -436,6 +436,14 @@ void Maxwell3D::CallMultiMethod(Core::System& system, u32 method, const u32* bas
|
|||
upload_state.ProcessData(base_start, amount);
|
||||
return;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(draw_inline_index):
|
||||
case MAXWELL3D_REG_INDEX(inline_index_2x16.even):
|
||||
case MAXWELL3D_REG_INDEX(inline_index_4x8.index0):
|
||||
if (shadow_state.shadow_ram_control != Regs::ShadowRamControl::Replay) {
|
||||
ProcessInlineIndexMultiData(method, base_start, amount);
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
for (u32 i = 0; i < amount; i++) {
|
||||
CallMethod(system, method, base_start[i], methods_pending - i <= 1);
|
||||
|
|
@ -622,6 +630,15 @@ void Maxwell3D::ProcessCBData(u32 value) {
|
|||
ProcessCBMultiData(&value, 1);
|
||||
}
|
||||
|
||||
void Maxwell3D::ProcessInlineIndexMultiData(u32 method, const u32* start_base, u32 amount) {
|
||||
if (amount == 0) {
|
||||
return;
|
||||
}
|
||||
const u32 argument = ProcessShadowRam(method, start_base[amount - 1]);
|
||||
ProcessDirtyRegisters(method, argument);
|
||||
draw_manager.SetInlineIndexBuffer(*this, method, start_base, amount);
|
||||
}
|
||||
|
||||
Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
|
||||
const GPUVAddr tic_address_gpu{regs.tex_header.Address() +
|
||||
tic_index * sizeof(Texture::TICEntry)};
|
||||
|
|
|
|||
|
|
@ -3077,6 +3077,7 @@ public:
|
|||
void DrawArrayIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology);
|
||||
void DrawIndexedIndirect(Maxwell3D& maxwell3d, Maxwell3D::Regs::PrimitiveTopology topology, u32 index_first, u32 index_count);
|
||||
void SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 index);
|
||||
void SetInlineIndexBuffer(Maxwell3D& maxwell3d, u32 method, const u32* base_start, u32 amount);
|
||||
void DrawBegin(Maxwell3D& maxwell3d);
|
||||
void DrawEnd(Maxwell3D& maxwell3d, u32 instance_count = 1, bool force_draw = false);
|
||||
void DrawIndexSmall(Maxwell3D& maxwell3d, u32 argument);
|
||||
|
|
@ -3193,6 +3194,8 @@ public:
|
|||
void ProcessCBData(u32 value);
|
||||
void ProcessCBMultiData(const u32* start_base, u32 amount);
|
||||
|
||||
void ProcessInlineIndexMultiData(u32 method, const u32* start_base, u32 amount);
|
||||
|
||||
private:
|
||||
void InitializeRegisterDefaults();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue