mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[MG_Backend, CI] (Disaggregated): reclaim abandoned wire objects only after texture uploads are idle
This commit is contained in:
@@ -3525,6 +3525,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return current->mapped + alignedCursor;
|
||||
}
|
||||
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
Bool VkTextureManager::WireUploadsAreIdle() {
|
||||
// An open batch still owns references even before it has a fence. Poll
|
||||
// submitted batches without waiting; reclamation is deferred if any lives.
|
||||
if (m_uploadBatchOpen) return false;
|
||||
ReclaimCompletedUploads();
|
||||
return m_pendingUploadReclaims.empty();
|
||||
}
|
||||
#endif
|
||||
|
||||
void VkTextureManager::FlushPendingUploads() {
|
||||
if (!m_uploadBatchOpen) {
|
||||
return;
|
||||
|
||||
@@ -480,6 +480,12 @@ public:
|
||||
// preserve-on-recreate copy are the existing callers. No-op when the
|
||||
// batch is empty.
|
||||
void FlushPendingUploads();
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// Non-blocking idle proof for wire-object retirement. Independent texture
|
||||
// submissions are not represented by VulkanRenderer's submit counter.
|
||||
Bool WireUploadsAreIdle();
|
||||
#endif
|
||||
|
||||
// Drains every frame slot's deferred image/view releases. Only valid when
|
||||
// the caller has proven every queue submission complete; used by the
|
||||
// present-less frame-boundary drain.
|
||||
|
||||
@@ -13089,6 +13089,18 @@ void main() {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
|
||||
// Texture uploads submit on this queue with their own fences. The
|
||||
// renderer watermark alone cannot prove images/views are idle.
|
||||
if (m_textureManager && !m_textureManager->WireUploadsAreIdle()) return false;
|
||||
// No preparation, recording or GPU work remains. A minimized Present
|
||||
// may have abandoned a recording tagged for a submission that will
|
||||
// never occur, so reclaim those future-tagged objects as well.
|
||||
CollectWireObjects(m_completedSubmitCounter, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Every submission is complete and nothing recorded references the
|
||||
// per-frame transients. Pure-reclaim work runs on every drain: it only
|
||||
// releases memory that is provably dead, never invalidates anything a
|
||||
|
||||
@@ -34,6 +34,23 @@ NEGATIVE = f"{PREFIX}1.MagmaRunAheadScenario.QueuedProgramRebindsKeepEachUniform
|
||||
CLEAR_ASSERTION = "the clear waited for apply instead of returning while its server batch was held"
|
||||
ERROR = re.compile(r"VUID-[A-Za-z0-9_-]+|SYNC-HAZARD-[A-Z_]+|Validation Error|\bERROR\b", re.I)
|
||||
LAYER = re.compile(r'Insert instance layer\s+["\']?VK_LAYER_KHRONOS_validation', re.I)
|
||||
# MobileGL's own diagnostics are not Vulkan-layer messages. Keep them visible
|
||||
# separately; an embedded validation/VUID/hazard message is never classified away.
|
||||
APPLICATION_ERROR = re.compile(r"^\[\d{2}:\d{2}:\d{2}(?:\.\d+)?\] \[(?:Linux|Android|Windows|macOS)[^\]]*/ERROR\]:")
|
||||
VALIDATION_MARKER = re.compile(r"VUID-|SYNC-HAZARD|\bvalidation\b", re.I)
|
||||
|
||||
|
||||
def split_diagnostics(stdout, private):
|
||||
validation, application = [], []
|
||||
for line in (stdout + "\n" + private).splitlines():
|
||||
if not ERROR.search(line):
|
||||
continue
|
||||
if APPLICATION_ERROR.search(line) and not VALIDATION_MARKER.search(line):
|
||||
application.append(line)
|
||||
else:
|
||||
validation.append(line)
|
||||
return validation, application
|
||||
|
||||
|
||||
|
||||
def write_json(path, data):
|
||||
@@ -183,9 +200,11 @@ def validation(tests, build, out):
|
||||
copied = copy.deepcopy(case)
|
||||
copied.set("name", name) # Raw gtest.xml remains unchanged beside this aggregate.
|
||||
junit.append(copied)
|
||||
lines = [line for line in (stdout + "\n" + private).splitlines() if ERROR.search(line)]
|
||||
lines, application_lines = split_diagnostics(stdout, private)
|
||||
(directory / "validation-errors.txt").write_text("\n".join(lines), encoding="utf-8")
|
||||
result.update(validation_error_lines=len(lines), layer_inserted=bool(LAYER.search(stdout + private)))
|
||||
(directory / "application-errors.txt").write_text("\n".join(application_lines), encoding="utf-8")
|
||||
result.update(validation_error_lines=len(lines), application_error_lines=len(application_lines),
|
||||
layer_inserted=bool(LAYER.search(stdout + private)))
|
||||
if result["returncode"] or failed or not result["private_log_present"]:
|
||||
raise RuntimeError("GPU case did not complete with a passing result and actual private log")
|
||||
if not result["layer_inserted"]:
|
||||
|
||||
Reference in New Issue
Block a user