mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 05:08:31 +09:00
[Fix] (DirectVulkan, GLImpl, MG_State, ShaderTranspiler): second audit round over the remaining memo sites
Six more verified defects from the residual memo/cache mechanisms: - Program resource cache (DirectVulkan reflection): glShaderStorageBlockBinding deliberately does not bump the backend state version, and the SSO pipeline composite is unnamed so the by-name in-place patch can never reach its slot - the composite kept serving pre-rebind SSBO bindings. The cache now keys on the program's block-binding version; a binding-only change re-applies the overrides by name instead of re-running spirv-reflect. SetShaderStorageBlockBinding also gains the equality bail-out its uniform-block sibling has, so the composite mirror's replay stops churning the version every draw. - LinkProgram's allowVSOnlyPrograms function-static latch never set its own initialized flag (dead memo, re-read every call) - and completing it would have frozen a per-backend capability across re-initialization. Replaced with a fresh per-link read from the null-checked active backend. - Query object registry: drained at full library teardown (DestroyAllQueryObjects, mirroring DestroyAllSyncObjects) - undeleted queries and their backend wrappers leaked across Destroy/Initialize cycles, stale ids stayed IsQuery == GL_TRUE in the re-initialized library, and a later delete could hand the old backend's wrapper to a different backend's DeleteBackendQuery. - Converted vertex streams and the host-side EBO max-index scan now SyncGpuWrites before reading the coherent mapping: XFB/SSBO/image writes are merely recorded at that point, so the conversion read pre-write bytes (the restart-index rewrite already synced; these two host reads did not). - Zero-stride converted bindings: both converters rejected stride 0, making the factory's documented single-element conversion unreachable and silently dropping every draw using such a binding; the stride is substituted with the element size for the one-element case. - DemoteFloat64Pass block relayout: measurement queued into the module eagerly, so a mid-struct failure left a half-relaid-out block (compacted offsets before the failing member, 64-bit offsets after) while claiming the block was left alone. Decoration writes are now collected and committed only when the whole block measures successfully.
This commit is contained in:
@@ -3323,6 +3323,11 @@ void main() {
|
||||
indexView.indexByteSize > bufferSize - indexView.indexByteOffset) {
|
||||
return false;
|
||||
}
|
||||
// Recorded-but-unexecuted GPU writes (XFB capture, SSBO, storage texel
|
||||
// buffer) land in the coherent mapping this scan is about to read;
|
||||
// submit-and-wait first, exactly like the restart-index rewrite does.
|
||||
// A no-op unless the gpu-write flag is set.
|
||||
indexBufferShared->SyncGpuWrites();
|
||||
indexBufferShared->SyncPersistentMappedRange();
|
||||
indexBytes = indexBufferShared->MappedData() + indexView.indexByteOffset;
|
||||
} else {
|
||||
@@ -3560,6 +3565,16 @@ void main() {
|
||||
const Uint8* sourceData, SizeT sourceStride,
|
||||
SizeT elementSize, SizeT elementCount,
|
||||
BufferSlice& outSlice) -> Bool {
|
||||
// A resolved stride of 0 is the binding model's "never advance" (see the
|
||||
// factory's layout notes): exactly one element is converted and every vertex
|
||||
// reads it. That single element is read at offset 0, so the stride is never
|
||||
// actually used - but both converters reject 0 as a degenerate input, which
|
||||
// made the documented single-element conversion unreachable and silently
|
||||
// dropped every draw using such a binding. Substitute the element's own
|
||||
// size; the caller's cache key still carries the distinct stride 0.
|
||||
if (sourceStride == 0 && elementCount == 1) {
|
||||
sourceStride = elementSize;
|
||||
}
|
||||
const void* uploadData = nullptr;
|
||||
VkDeviceSize uploadSize = 0;
|
||||
switch (conversion) {
|
||||
@@ -3693,6 +3708,12 @@ void main() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A GPU-written source (XFB capture, SSBO, storage texel buffer) has its
|
||||
// bytes produced by commands that are merely RECORDED at this point, and
|
||||
// MappedData() aliases the coherent GPU memory they will write into -
|
||||
// converting now would read pre-write garbage. Submit-and-wait first,
|
||||
// mirroring the restart-index rewrite; a flag-test no-op otherwise.
|
||||
sourceBufferShared->SyncGpuWrites();
|
||||
sourceBufferShared->SyncPersistentMappedRange();
|
||||
const SizeT availableElementCount =
|
||||
sourceStride == 0 ? 1 : 1 + (sourceSize - baseOffset - elementSize) / sourceStride;
|
||||
|
||||
Reference in New Issue
Block a user