early-access version 3098

main
pineappleEA 2022-11-08 03:37:36 +01:00
parent 9b08ac8a80
commit ca0b9fc44b
11 changed files with 60 additions and 63 deletions

View File

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

View File

@ -27,16 +27,12 @@ namespace Kernel {
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_, SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
ServiceThreadType thread_type) ServiceThreadType thread_type)
: kernel{kernel_} { : kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew
if (thread_type == ServiceThreadType::CreateNew) { ? kernel.CreateServiceThread(service_name_)
service_thread = kernel.CreateServiceThread(service_name_); : kernel.GetDefaultServiceThread()} {}
} else {
service_thread = kernel.GetDefaultServiceThread();
}
}
SessionRequestHandler::~SessionRequestHandler() { SessionRequestHandler::~SessionRequestHandler() {
kernel.ReleaseServiceThread(service_thread.lock()); kernel.ReleaseServiceThread(service_thread);
} }
void SessionRequestHandler::AcceptSession(KServerPort* server_port) { void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
@ -49,7 +45,7 @@ void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
void SessionRequestHandler::RegisterSession(KServerSession* server_session, void SessionRequestHandler::RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager) { std::shared_ptr<SessionRequestManager> manager) {
manager->SetSessionHandler(shared_from_this()); manager->SetSessionHandler(shared_from_this());
service_thread.lock()->RegisterServerSession(server_session, manager); service_thread.RegisterServerSession(server_session, manager);
server_session->Close(); server_session->Close();
} }

View File

@ -82,13 +82,13 @@ public:
void RegisterSession(KServerSession* server_session, void RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager); std::shared_ptr<SessionRequestManager> manager);
std::weak_ptr<ServiceThread> GetServiceThread() const { ServiceThread& GetServiceThread() const {
return service_thread; return service_thread;
} }
protected: protected:
KernelCore& kernel; KernelCore& kernel;
std::weak_ptr<ServiceThread> service_thread; ServiceThread& service_thread;
}; };
using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>; using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
@ -154,7 +154,7 @@ public:
session_handler = std::move(handler); session_handler = std::move(handler);
} }
std::weak_ptr<ServiceThread> GetServiceThread() const { ServiceThread& GetServiceThread() const {
return session_handler->GetServiceThread(); return session_handler->GetServiceThread();
} }

View File

@ -93,7 +93,7 @@ struct KernelCore::Impl {
RegisterHostThread(nullptr); RegisterHostThread(nullptr);
default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread"); default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
} }
void InitializeCores() { void InitializeCores() {
@ -782,33 +782,31 @@ struct KernelCore::Impl {
search->second(system.ServiceManager(), server_port); search->second(system.ServiceManager(), server_port);
} }
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel, Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
const std::string& name) { auto* ptr = new ServiceThread(kernel, name);
auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, name);
service_threads_manager.QueueWork( service_threads_manager.QueueWork(
[this, service_thread]() { service_threads.emplace(service_thread); }); [this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
return service_thread; return *ptr;
} }
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
if (auto strong_ptr = service_thread.lock()) { auto* ptr = &service_thread;
if (strong_ptr == default_service_thread.lock()) {
// Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
}
service_threads_manager.QueueWork( if (ptr == default_service_thread) {
[this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); }); // Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
} }
service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
} }
void ClearServiceThreads() { void ClearServiceThreads() {
service_threads_manager.QueueWork([this] { service_threads_manager.QueueWork([this] {
service_threads.clear(); service_threads.clear();
default_service_thread.reset(); default_service_thread = nullptr;
service_thread_barrier.Sync(); service_thread_barrier.Sync();
}); });
service_thread_barrier.Sync(); service_thread_barrier.Sync();
@ -884,8 +882,8 @@ struct KernelCore::Impl {
std::unique_ptr<KMemoryLayout> memory_layout; std::unique_ptr<KMemoryLayout> memory_layout;
// Threads used for services // Threads used for services
std::unordered_set<std::shared_ptr<ServiceThread>> service_threads; std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
std::weak_ptr<ServiceThread> default_service_thread; ServiceThread* default_service_thread{};
Common::ThreadWorker service_threads_manager; Common::ThreadWorker service_threads_manager;
Common::Barrier service_thread_barrier; Common::Barrier service_thread_barrier;
@ -1258,15 +1256,15 @@ void KernelCore::ExitSVCProfile() {
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]); MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
} }
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) { Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
return impl->CreateServiceThread(*this, name); return impl->CreateServiceThread(*this, name);
} }
std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const { Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
return impl->default_service_thread; return *impl->default_service_thread;
} }
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
impl->ReleaseServiceThread(service_thread); impl->ReleaseServiceThread(service_thread);
} }

View File

@ -309,24 +309,24 @@ public:
* See GetDefaultServiceThread. * See GetDefaultServiceThread.
* @param name String name for the ServerSession creating this thread, used for debug * @param name String name for the ServerSession creating this thread, used for debug
* purposes. * purposes.
* @returns The a weak pointer newly created service thread. * @returns A reference to the newly created service thread.
*/ */
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name); Kernel::ServiceThread& CreateServiceThread(const std::string& name);
/** /**
* Gets the default host service thread, which executes HLE service requests. Unless service * Gets the default host service thread, which executes HLE service requests. Unless service
* requests need to block on the host, the default service thread should be used in favor of * requests need to block on the host, the default service thread should be used in favor of
* creating a new service thread. * creating a new service thread.
* @returns The a weak pointer for the default service thread. * @returns A reference to the default service thread.
*/ */
std::weak_ptr<Kernel::ServiceThread> GetDefaultServiceThread() const; Kernel::ServiceThread& GetDefaultServiceThread() const;
/** /**
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when * Releases a HLE service thread, instructing KernelCore to free it. This should be called when
* the ServerSession associated with the thread is destroyed. * the ServerSession associated with the thread is destroyed.
* @param service_thread Service thread to release. * @param service_thread Service thread to release.
*/ */
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread); void ReleaseServiceThread(Kernel::ServiceThread& service_thread);
/// Workaround for single-core mode when preempting threads while idle. /// Workaround for single-core mode when preempting threads while idle.
bool IsPhantomModeForSingleCore() const; bool IsPhantomModeForSingleCore() const;

View File

@ -383,7 +383,7 @@ void EmitInvocationInfo(EmitContext& ctx, IR::Inst& inst) {
switch (ctx.stage) { switch (ctx.stage) {
case Stage::TessellationControl: case Stage::TessellationControl:
case Stage::TessellationEval: case Stage::TessellationEval:
ctx.Add("SHL.U {}.x, primitive.vertexcount, 16;", inst); ctx.Add("SHL.U {}.x,primitive.vertexcount,16;", inst);
break; break;
default: default:
LOG_WARNING(Shader, "(STUBBED) called"); LOG_WARNING(Shader, "(STUBBED) called");

View File

@ -204,7 +204,7 @@ public:
Id workgroup_id{}; Id workgroup_id{};
Id local_invocation_id{}; Id local_invocation_id{};
Id invocation_id{}; Id invocation_id{};
Id patch_vertices_in; Id patch_vertices_in{};
Id sample_id{}; Id sample_id{};
Id is_helper_invocation{}; Id is_helper_invocation{};
Id subgroup_local_invocation_id{}; Id subgroup_local_invocation_id{};

View File

@ -103,26 +103,29 @@ void MaxwellDMA::Launch() {
const bool is_src_pitch = IsPitchKind(static_cast<PTEKind>(src_kind)); const bool is_src_pitch = IsPitchKind(static_cast<PTEKind>(src_kind));
const bool is_dst_pitch = IsPitchKind(static_cast<PTEKind>(dst_kind)); const bool is_dst_pitch = IsPitchKind(static_cast<PTEKind>(dst_kind));
if (!is_src_pitch && is_dst_pitch) { if (!is_src_pitch && is_dst_pitch) {
std::vector<u8> tmp_buffer(regs.line_length_in); UNIMPLEMENTED_IF(regs.line_length_in % 16 != 0);
std::vector<u8> dst_buffer(regs.line_length_in); UNIMPLEMENTED_IF(regs.offset_in % 16 != 0);
memory_manager.ReadBlockUnsafe(regs.offset_in, tmp_buffer.data(), UNIMPLEMENTED_IF(regs.offset_out % 16 != 0);
regs.line_length_in); std::vector<u8> tmp_buffer(16);
for (u32 offset = 0; offset < regs.line_length_in; ++offset) { for (u32 offset = 0; offset < regs.line_length_in; offset += 16) {
dst_buffer[offset] = memory_manager.ReadBlockUnsafe(
tmp_buffer[convert_linear_2_blocklinear_addr(regs.offset_in + offset) - convert_linear_2_blocklinear_addr(regs.offset_in + offset),
regs.offset_in]; tmp_buffer.data(), tmp_buffer.size());
memory_manager.WriteBlock(regs.offset_out + offset, tmp_buffer.data(),
tmp_buffer.size());
} }
memory_manager.WriteBlock(regs.offset_out, dst_buffer.data(), regs.line_length_in);
} else if (is_src_pitch && !is_dst_pitch) { } else if (is_src_pitch && !is_dst_pitch) {
std::vector<u8> tmp_buffer(regs.line_length_in); UNIMPLEMENTED_IF(regs.line_length_in % 16 != 0);
std::vector<u8> dst_buffer(regs.line_length_in); UNIMPLEMENTED_IF(regs.offset_in % 16 != 0);
memory_manager.ReadBlockUnsafe(regs.offset_in, tmp_buffer.data(), UNIMPLEMENTED_IF(regs.offset_out % 16 != 0);
regs.line_length_in); std::vector<u8> tmp_buffer(16);
for (u32 offset = 0; offset < regs.line_length_in; ++offset) { for (u32 offset = 0; offset < regs.line_length_in; offset += 16) {
dst_buffer[convert_linear_2_blocklinear_addr(regs.offset_out + offset) - memory_manager.ReadBlockUnsafe(regs.offset_in + offset, tmp_buffer.data(),
regs.offset_out] = tmp_buffer[offset]; tmp_buffer.size());
memory_manager.WriteBlock(
convert_linear_2_blocklinear_addr(regs.offset_out + offset),
tmp_buffer.data(), tmp_buffer.size());
} }
memory_manager.WriteBlock(regs.offset_out, dst_buffer.data(), regs.line_length_in);
} else { } else {
if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) { if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) {
std::vector<u8> tmp_buffer(regs.line_length_in); std::vector<u8> tmp_buffer(regs.line_length_in);

View File

@ -76,7 +76,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
} }
break; break;
case Shader::Stage::TessellationEval: case Shader::Stage::TessellationEval:
// Flip the face, as opengl's drawing is also flipped // Flip the face, as OpenGL's drawing is flipped.
info.tess_clockwise = key.tessellation_clockwise == 0; info.tess_clockwise = key.tessellation_clockwise == 0;
info.tess_primitive = [&key] { info.tess_primitive = [&key] {
switch (key.tessellation_primitive) { switch (key.tessellation_primitive) {

View File

@ -158,7 +158,7 @@ int CompatDB::nextId() const {
case CompatDBPage::Audio: case CompatDBPage::Audio:
return static_cast<int>(CompatDBPage::Final); return static_cast<int>(CompatDBPage::Final);
case CompatDBPage::Final: case CompatDBPage::Final:
return static_cast<int>(CompatDBPage::Final); return -1;
default: default:
LOG_ERROR(Frontend, "Unexpected page: {}", currentId()); LOG_ERROR(Frontend, "Unexpected page: {}", currentId());
return static_cast<int>(CompatDBPage::Intro); return static_cast<int>(CompatDBPage::Intro);

View File

@ -291,7 +291,7 @@
<item row="6" column="0"> <item row="6" column="0">
<widget class="QRadioButton" name="radioButton_Graphical_No"> <widget class="QRadioButton" name="radioButton_Graphical_No">
<property name="text"> <property name="text">
<string>None Everything is rendered as it looks on the Nintendo Switch</string> <string>None Everything is rendered as it looks on the Nintendo Switch</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -350,7 +350,7 @@
<item row="6" column="0"> <item row="6" column="0">
<widget class="QRadioButton" name="radioButton_Audio_No"> <widget class="QRadioButton" name="radioButton_Audio_No">
<property name="text"> <property name="text">
<string>None Audio is played perfectly</string> <string>None Audio is played perfectly</string>
</property> </property>
</widget> </widget>
</item> </item>