Fix indirect draws with direct buffers

We need to wait on the GPFIFO manually as we won't hit the traps when accesing the indirect params with direct as we usually would.
This commit is contained in:
Billy Laws 2022-12-31 23:32:05 +00:00
parent 68ad052cb1
commit 45bbf3bb2a
3 changed files with 23 additions and 3 deletions

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <condition_variable>
#include <mutex>
#include <range/v3/view.hpp> #include <range/v3/view.hpp>
#include <adrenotools/driver.h> #include <adrenotools/driver.h>
#include <common/settings.h> #include <common/settings.h>
@ -555,7 +557,7 @@ namespace skyline::gpu::interconnect {
} }
} }
void CommandExecutor::Submit(std::function<void()> &&callback) { void CommandExecutor::Submit(std::function<void()> &&callback, bool wait) {
for (const auto &flushCallback : flushCallbacks) for (const auto &flushCallback : flushCallbacks)
flushCallback(); flushCallback();
@ -581,6 +583,21 @@ namespace skyline::gpu::interconnect {
callback(); callback();
ResetInternal(); ResetInternal();
if (wait) {
std::condition_variable cv;
std::mutex mutex;
bool gpuDone{};
waiterThread.Queue(nullptr, [&cv, &mutex, &gpuDone] {
std::scoped_lock lock{mutex};
gpuDone = true;
cv.notify_one();
});
std::unique_lock lock{mutex};
cv.wait(lock, [&gpuDone] { return gpuDone; });
}
} }
void CommandExecutor::LockPreserve() { void CommandExecutor::LockPreserve() {

View File

@ -301,8 +301,9 @@ namespace skyline::gpu::interconnect {
/** /**
* @brief Execute all the nodes and submit the resulting command buffer to the GPU * @brief Execute all the nodes and submit the resulting command buffer to the GPU
* @param callback A function to call upon GPU completion of the submission * @param callback A function to call upon GPU completion of the submission
* @param wait Whether to wait synchronously for GPU completion of the submit
*/ */
void Submit(std::function<void()> &&callback = {}); void Submit(std::function<void()> &&callback = {}, bool wait = false);
/** /**
* @brief Locks all preserve attached buffers/textures * @brief Locks all preserve attached buffers/textures

View File

@ -1,7 +1,9 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <gpu.h>
#include <common/signal.h> #include <common/signal.h>
#include <common/settings.h>
#include <loader/loader.h> #include <loader/loader.h>
#include <kernel/types/KProcess.h> #include <kernel/types/KProcess.h>
#include <soc.h> #include <soc.h>
@ -156,7 +158,7 @@ namespace skyline::soc::gm20b {
void ChannelGpfifo::Process(GpEntry gpEntry) { void ChannelGpfifo::Process(GpEntry gpEntry) {
// Submit if required by the GpEntry, this is needed as some games dynamically generate pushbuffer contents // Submit if required by the GpEntry, this is needed as some games dynamically generate pushbuffer contents
if (gpEntry.sync == GpEntry::Sync::Wait) if (gpEntry.sync == GpEntry::Sync::Wait)
channelCtx.executor.Submit(); channelCtx.executor.Submit({}, *state.settings->useDirectMemoryImport);
if (!gpEntry.size) { if (!gpEntry.size) {
// This is a GPFIFO control entry, all control entries have a zero length and contain no pushbuffers // This is a GPFIFO control entry, all control entries have a zero length and contain no pushbuffers