early-access version 3144

This commit is contained in:
pineappleEA 2022-11-23 01:24:32 +01:00
parent d9623847ea
commit 1f43e53a82
5 changed files with 82 additions and 77 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3143. This is the source code for early-access 3144.
## Legal Notice ## Legal Notice

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/k_handle_table.h" #include "core/hle/kernel/k_handle_table.h"
#include "core/hle/kernel/k_process.h"
namespace Kernel { namespace Kernel {
@ -82,6 +83,22 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) {
R_SUCCEED(); R_SUCCEED();
} }
KScopedAutoObject<KAutoObject> KHandleTable::GetObjectForIpc(Handle handle,
KThread* cur_thread) const {
// Handle pseudo-handles.
ASSERT(cur_thread != nullptr);
if (handle == Svc::PseudoHandle::CurrentProcess) {
auto* const cur_process = cur_thread->GetOwnerProcess();
ASSERT(cur_process != nullptr);
return cur_process;
}
if (handle == Svc::PseudoHandle::CurrentThread) {
return cur_thread;
}
return GetObjectForIpcWithoutPseudoHandle(handle);
}
Result KHandleTable::Reserve(Handle* out_handle) { Result KHandleTable::Reserve(Handle* out_handle) {
KScopedDisableDispatch dd{m_kernel}; KScopedDisableDispatch dd{m_kernel};
KScopedSpinLock lk(m_lock); KScopedSpinLock lk(m_lock);

View file

@ -113,21 +113,7 @@ public:
return this->GetObjectImpl(handle); return this->GetObjectImpl(handle);
} }
KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const { KScopedAutoObject<KAutoObject> GetObjectForIpc(Handle handle, KThread* cur_thread) const;
// Handle pseudo-handles.
ASSERT(cur_thread != nullptr);
if (handle == Svc::PseudoHandle::CurrentProcess) {
auto* const cur_process =
static_cast<KAutoObject*>(static_cast<void*>(cur_thread->GetOwnerProcess()));
ASSERT(cur_process != nullptr);
return cur_process;
}
if (handle == Svc::PseudoHandle::CurrentThread) {
return static_cast<KAutoObject*>(cur_thread);
}
return GetObjectForIpcWithoutPseudoHandle(handle);
}
KScopedAutoObject<KAutoObject> GetObjectByIndex(Handle* out_handle, size_t index) const { KScopedAutoObject<KAutoObject> GetObjectByIndex(Handle* out_handle, size_t index) const {
KScopedDisableDispatch dd{m_kernel}; KScopedDisableDispatch dd{m_kernel};

View file

@ -126,6 +126,7 @@ void Maxwell3D::InitializeRegisterDefaults() {
draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
draw_command[MAXWELL3D_REG_INDEX(draw.instance_id)] = true;
} }
void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@ -288,31 +289,58 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS, ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure"); "Invalid Maxwell3D register, increase the size of the Regs structure");
const u32 argument = ProcessShadowRam(method, method_argument);
ProcessDirtyRegisters(method, argument);
if (draw_command[method]) { if (draw_command[method]) {
regs.reg_array[method] = method_argument; regs.reg_array[method] = method_argument;
deferred_draw_method.push_back(method); deferred_draw_method.push_back(method);
auto u32_to_u8 = [&](const u32 argument) { auto update_inline_index = [&](const u32 index) {
inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff)); inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff));
inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8)); inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8));
inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16)); inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16));
inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24)); inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24));
draw_mode = DrawMode::InlineIndex;
}; };
if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) { switch (method) {
u32_to_u8(method_argument); case MAXWELL3D_REG_INDEX(draw.end):
} else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) { switch (draw_mode) {
u32_to_u8(regs.inline_index_2x16.even); case DrawMode::General:
u32_to_u8(regs.inline_index_2x16.odd); ProcessDraw(1);
} else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) { break;
u32_to_u8(regs.inline_index_4x8.index0); case DrawMode::InlineIndex:
u32_to_u8(regs.inline_index_4x8.index1); regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
u32_to_u8(regs.inline_index_4x8.index2); regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
u32_to_u8(regs.inline_index_4x8.index3); ProcessDraw(1);
inline_index_draw_indexes.clear();
break;
case DrawMode::Instance:
break;
}
break;
case MAXWELL3D_REG_INDEX(draw_inline_index):
update_inline_index(method_argument);
break;
case MAXWELL3D_REG_INDEX(inline_index_2x16.even):
update_inline_index(regs.inline_index_2x16.even);
update_inline_index(regs.inline_index_2x16.odd);
break;
case MAXWELL3D_REG_INDEX(inline_index_4x8.index0):
update_inline_index(regs.inline_index_4x8.index0);
update_inline_index(regs.inline_index_4x8.index1);
update_inline_index(regs.inline_index_4x8.index2);
update_inline_index(regs.inline_index_4x8.index3);
break;
case MAXWELL3D_REG_INDEX(draw.instance_id):
draw_mode =
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
? DrawMode::Instance
: DrawMode::General;
break;
} }
} else { } else {
ProcessDeferredDraw(); ProcessDeferredDraw();
const u32 argument = ProcessShadowRam(method, method_argument);
ProcessDirtyRegisters(method, argument);
ProcessMethodCall(method, argument, method_argument, is_last_call); ProcessMethodCall(method, argument, method_argument, is_last_call);
} }
} }
@ -626,57 +654,27 @@ void Maxwell3D::ProcessDraw(u32 instance_count) {
} }
void Maxwell3D::ProcessDeferredDraw() { void Maxwell3D::ProcessDeferredDraw() {
if (deferred_draw_method.empty()) { if (draw_mode != DrawMode::Instance || deferred_draw_method.empty()) {
return; return;
} }
enum class DrawMode {
Undefined,
General,
Instance,
};
DrawMode draw_mode{DrawMode::Undefined};
u32 method_count = static_cast<u32>(deferred_draw_method.size()); u32 method_count = static_cast<u32>(deferred_draw_method.size());
u32 method = deferred_draw_method[method_count - 1]; u32 instance_count = 1;
if (MAXWELL3D_REG_INDEX(draw.end) != method) { u32 vertex_buffer_count = 0;
return; u32 index_buffer_count = 0;
} for (u32 index = 0; index < method_count; ++index) {
draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || u32 method = deferred_draw_method[index];
(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
? DrawMode::Instance instance_count = ++vertex_buffer_count;
: DrawMode::General; } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
u32 instance_count = 0; instance_count = ++index_buffer_count;
if (draw_mode == DrawMode::Instance) {
u32 vertex_buffer_count = 0;
u32 index_buffer_count = 0;
for (u32 index = 0; index < method_count; ++index) {
method = deferred_draw_method[index];
if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) {
instance_count = ++vertex_buffer_count;
} else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
instance_count = ++index_buffer_count;
}
}
ASSERT_MSG(!(vertex_buffer_count && index_buffer_count),
"Instance both indexed and direct?");
} else {
instance_count = 1;
for (u32 index = 0; index < method_count; ++index) {
method = deferred_draw_method[index];
if (MAXWELL3D_REG_INDEX(draw_inline_index) == method ||
MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method ||
MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
break;
}
} }
} }
ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?");
ProcessDraw(instance_count); ProcessDraw(instance_count);
deferred_draw_method.clear(); deferred_draw_method.clear();
inline_index_draw_indexes.clear();
} }
} // namespace Tegra::Engines } // namespace Tegra::Engines

View file

@ -3148,10 +3148,12 @@ private:
/// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro)
void ProcessTopologyOverride(); void ProcessTopologyOverride();
void ProcessDraw(u32 instance_count = 1); /// Handles deferred draw(e.g., instance draw).
void ProcessDeferredDraw(); void ProcessDeferredDraw();
/// Handles a draw.
void ProcessDraw(u32 instance_count = 1);
/// Returns a query's value or an empty object if the value will be deferred through a cache. /// Returns a query's value or an empty object if the value will be deferred through a cache.
std::optional<u64> GetQueryResult(); std::optional<u64> GetQueryResult();
@ -3178,6 +3180,8 @@ private:
std::array<bool, Regs::NUM_REGS> draw_command{}; std::array<bool, Regs::NUM_REGS> draw_command{};
std::vector<u32> deferred_draw_method; std::vector<u32> deferred_draw_method;
enum class DrawMode : u32 { General = 0, Instance, InlineIndex };
DrawMode draw_mode{DrawMode::General};
}; };
#define ASSERT_REG_POSITION(field_name, position) \ #define ASSERT_REG_POSITION(field_name, position) \