Repository navigation
Conversation
This was referenced Nov 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LoadModelDemo, MipmapDemo, and MultiSamplingDemo retain host-visible vertex/index staging buffers as renderer members until model destruction. Their draw paths use only device-local geometry after the synchronous uploads complete. Initialization also performs two separate geometry submissions and fence waits.
This architecture change gives those existing upload resources a completion-bounded lifetime. Candidate comparison: descriptor rebinding could enable compute-pipeline reuse but needs a wider update contract and concrete caller migration; partial/pitched texture uploads still need an incremental-update workload and format/pitch requirements. Scoped mesh staging has three actual OBJ-model consumers, clear ownership boundaries, and directly verifiable resource benefits. Open #132 concerns compute reductions and does not overlap; recent timestamp, image-recording, and specialization work is already on master. Scope is Vulkan only, with no shared dependency or other backend implementation changes.
Solution
Remove each renderer's two staging members and their allocations from
CreateBuffers(). Allocate/map both staging buffers locally inInit(), sized from the existing device-local destinations, then upload both through the existingVulkanBuffer::CopyBuffersAPI. Its checked fence wait completes before local staging destruction; its memory barriers make transfer writes available to subsequent geometry reads.Each demo automatically uses this through its unchanged
Init(...),UpdateUniformBuffer(...), andRender(...)calls. Device-local geometry, uniform/texture ownership, and CPU mesh vectors retain their existing lifetimes. Compared with explicitly resetting members after two separate copies, local ownership directly expresses the lifetime and the batch supplies one completion boundary. A new uploader abstraction or asynchronous lifetime manager is unnecessary for these synchronous callers. Resource release follows the Vulkan memory completion requirement.Validation
The final source tree was unchanged between these full runs and the commit. All default enabled targets/examples built. Actual core flags include
-O3 -DNDEBUGand warnings as errors, despite the runner requesting Debug../scripts/run.sh -t macos -r tests./scripts/run.sh -t arm64-v8a -r testsVerified exact local/
adb shellinvocations, matching individual RUN/OK pairs, start/completion/pass summaries, and successfulset -erunner execution. Platform logs and macOS temporary outputs were preserved separately. Initial full runs also passed; both platforms were repeated after the final test-format/include adjustment.The new default Vulkan test links the actual MipmapDemo renderer and shaders. It generates deterministic OBJ/PPM files, calls the unchanged
Init, deletes the files, then renders three independently created/destroyed model instances for two offscreen frames each. Command/fence reuse, depth testing, indexed geometry fetch, and image readback are exercised after staging leaves scope. Independent CPU edge equations check 3,724 RGBA pixels/frame, including interior and cleared exterior; pixels close to edges are excluded to avoid rasterization-edge convention dependence. No external asset download or window is required.macOS: Apple M6/MoltenVK 1.4.1, macOS 27.0.1, installed Xcode SDK 27.2 selected with shell-local
SDKROOT, Apple Clang 21.0.0 (clang-2100.4.1.1), CMake 4.4.4, Vulkan SDK 1.4.350.0, glslc 2026.2, Slang 2026.8. Khronos validation available/requested; no observed validation errors or warnings.Android:
adb devices -lbefore each run confirmed the sole authorized USB physical target, 2210132C/nuwa, serial1dda2807, Android 13/API 33, qcom/Adreno 740, empty emulator property. FixedANDROID_SERIAL=1dda2807. Reused compatible installed NDK 28.2.13676358/r28c, Android Clang 19.0.1, target API 34, ADB 37.0.1 and JDK 17. Explicit SDK activation/PATH supplied CMake, adb, glslc, slangc, xxd. Android validation-layer availability was not independently established. No dependency installation, new license acceptance, sudo, profile change, APK installation, or device-setting change.Resource and lifetime evidence
Same macOS device/toolchain/core configuration, original-master versus final production code. API-dump traces track every allocation/free handle and submit between initialization markers; all traced allocations are eventually freed. The synthetic fixture ran three lifecycles per version. Separate original/final probes also initialized existing
examples/data/viking_room.{obj,png}: 3,566 unique vertices, 11,484 indices.Viking releases 160,048 bytes of Vulkan allocations before rendering: 114,112 vertex bytes + 45,936 index bytes. The synthetic case releases 120 bytes across each lifecycle. These are observed Vulkan allocation sizes/call counts on MoltenVK, not RSS or physical-heap measurements. Peak staging demand and CPU mesh retention are unchanged. The same source-level ownership change applies to the other two migrated callers.
The synthetic trace is reproducible with the SDK's API-dump layer:
VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_api_dump ./build/macos/tests/vulkan/vulkan_tests '--gtest_filter=VulkanModelUploadTest.*'Raw baseline/final traces, original/final probe sources/commands, fixture hashes, build/test logs, and verification summaries are retained in this worktree's ignored
build/daily-mesh-upload-20261102/. The Viking probe initializes resources without rendering that asset. Android allocation counters were not instrumented. No latency, FPS, throughput, or cross-vendor performance claim is made.Changes
examples/vulkan/LoadModelDemo/RenderModel.cppexamples/vulkan/LoadModelDemo/RenderModel.hexamples/vulkan/MipmapDemo/RenderModel.cppexamples/vulkan/MipmapDemo/RenderModel.hexamples/vulkan/MultiSamplingDemo/RenderModel.cppexamples/vulkan/MultiSamplingDemo/RenderModel.htests/vulkan/CMakeLists.txttests/vulkan/VulkanModelUploadTest.cppImplementation/ownership +63/-42; tests/build +218/-0; benchmarks 0; project documentation +0/-0. Total 8 files, +281/-42 = 323 changed lines, relative to freshly fetched
origin/masterat0dc12da8ee3f6b69ed18a0e6c817e9e436e85906.Risk
Initialization/render signatures and synchronous behavior are preserved. Example class layouts shrink, so consumers compiling these example headers must rebuild. Callers still synchronize queue access and wait before destroying renderers referenced by pending draws. Reinitializing an already initialized renderer remains outside the existing supported lifecycle.
The MipmapDemo path is rendered/read back on both platforms. The other two windowed model renderers were built on macOS; their draw paths were not exercised. Allocation/device-loss injection, windowed visual behavior, and additional GPU vendors were not tested. Texture uploads, parsing, shaders, uniform updates, multisampling configuration, and library APIs are unchanged. Full default tests, including other backends, ran on both platforms.