Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gpu/render/rx_nvn.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ void rx_nvn_submit(const uint64_t *handles, int n);
void rx_nvn_submit_q(const uint64_t *handles, int n, uint64_t queue);
/* fence value of everything submitted so far; waits until the GPU reached a fence (1: reached, 0: timed out) */
uint64_t rx_nvn_fence(void);
uint64_t rx_nvn_fence_q(uint64_t queue); /* (hookshot) a fence of one queue */
/* submits and presents queued so far / replayed so far (recordings released after a submit stay until it replayed) */
uint64_t rx_nvn_pushed(void);
uint64_t rx_nvn_replayed(void);
Expand Down
2 changes: 2 additions & 0 deletions gpu/vk/vk_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ typedef struct MkwVkRenderer {
int (*option)(int id); /* (hookshot, the Insert menu) 0: game time follows the clock, 1: the menu is open, 2: dynamic resolution, 3: its fixed scale in percent, 4: the controllers count behind other windows, 5: text speed (0 normal to 3 instant) */
/* a submit with its queue */
void (*nvn_submit_q)(const uint64_t *handles, int n, uint64_t queue);
/* (hookshot) a fence of one queue: the value its own last submission signals (nvnQueueFenceSync) */
uint64_t (*nvn_fence_q)(uint64_t queue);
} MkwVkRenderer;

/* the DLL's one export: null when Vulkan is not usable (the executable then falls back to WebGPU) */
Expand Down
1 change: 1 addition & 0 deletions gpu/vk/vk_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ void memory_collect_written();
void memory_capture_submit();
/// The replay of the next submit: its capture (false: none, the pages are collected now as before)
bool memory_take_capture(uint64_t value, uint64_t completed);
bool memory_capture_now(uint64_t value, uint64_t completed); // (hookshot: made and taken at once)
/// The submission the replay records next (bindings note it: a pool's mirror is in use until it is done)
void memory_recording_value(uint64_t value, uint64_t completed);
/// RX_VK_TEX_CAPTURE (on with the capture; =0 off): the storage of a texture uploaded from guest memory joins the
Expand Down
43 changes: 30 additions & 13 deletions gpu/vk/vk_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,8 +1024,16 @@ void copy_pages(const uint32_t* pages, int64_t n, uint8_t* out, uint8_t* ok) {
copy_helpers.done.wait(lk, [] { return copy_helpers.pending == 0; });
}

std::unique_ptr<Capture> capture_make();
void memory_capture_submit() {
if (!capture_on()) return;
std::unique_ptr<Capture> c = capture_make();
if (!c) return;
std::lock_guard lk(cap_mu);
captures.push_back(std::move(c));
}
/// (the pages the CPU wrote since the last capture, copied now: a submit's capture, or memory_capture_now's)
std::unique_ptr<Capture> capture_make() {
if (!capture_on()) return nullptr;
const auto t0 = std::chrono::steady_clock::now();
std::unique_ptr<Capture> c;
{
Expand Down Expand Up @@ -1099,8 +1107,7 @@ void memory_capture_submit() {
ms = ms_lock = ms_scan = 0, written = copied = 0;
}
}
std::lock_guard lk(cap_mu);
captures.push_back(std::move(c));
return c;
}

bool capture_owns(uint64_t guest) {
Expand All @@ -1119,16 +1126,7 @@ void memory_recording_value(uint64_t value, uint64_t completed) {
mem_rec_value = value;
if (completed > mem_completed) mem_completed = completed;
}
bool memory_take_capture(uint64_t value, uint64_t completed) {
if (completed > mem_completed) mem_completed = completed;
if (!capture_on()) return false;
std::unique_ptr<Capture> c;
{
std::lock_guard lk(cap_mu);
if (captures.empty()) return false;
c = std::move(captures.front());
captures.pop_front();
}
bool take_capture(std::unique_ptr<Capture> c, uint64_t value, uint64_t completed) {
const auto tk0 = std::chrono::steady_clock::now();
std::lock_guard lk(pools_mu);
cur_cap_value = value;
Expand Down Expand Up @@ -1209,6 +1207,25 @@ bool memory_take_capture(uint64_t value, uint64_t completed) {
}
return true;
}
bool memory_take_capture(uint64_t value, uint64_t completed) {
if (completed > mem_completed) mem_completed = completed;
if (!capture_on()) return false;
std::unique_ptr<Capture> c;
{
std::lock_guard lk(cap_mu);
if (captures.empty()) return false;
c = std::move(captures.front());
captures.pop_front();
}
return take_capture(std::move(c), value, completed);
}
/// (hookshot) A capture made and taken at once, for a submission going on from a wait the CPU's signal met
/// (vk_replay.cpp resume_queue): the CPU's writes up to that signal, which the console's GPU reads after its wait
bool memory_capture_now(uint64_t value, uint64_t completed) {
if (completed > mem_completed) mem_completed = completed;
std::unique_ptr<Capture> c = capture_make();
return c && take_capture(std::move(c), value, completed);
}

namespace {

Expand Down
Loading
Loading