early-access version 3098
This commit is contained in:
parent
9b08ac8a80
commit
ca0b9fc44b
11 changed files with 60 additions and 63 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
|
||||||
|
if (ptr == default_service_thread) {
|
||||||
// Nothing to do here, the service is using default_service_thread, which will be
|
// Nothing to do here, the service is using default_service_thread, which will be
|
||||||
// released on shutdown.
|
// released on shutdown.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
service_threads_manager.QueueWork(
|
service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
|
||||||
[this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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{};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue