mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +09:00
Create 6 / Flywheel 1.0.6 now renders correctly with both flywheel:instancing and flywheel:indirect on DirectGLES and DirectVulkan (verified in-game on Adreno 830: waterwheels and cogwheels solid, animated, correct pairing, no crashes across all four combinations). - MG_State/MG_Impl: sync explicitly-ranged SSBO bindings of FLUSH_EXPLICIT persistent maps to the backend before compute dispatches. Flywheel writes its scatter-copy descriptors into the staging ring's persistent map and never flushes that span (UB per spec, works on drivers whose maps alias GPU-visible memory); our maps alias the CPU shadow, so the descriptors never reached the GPU: the scatter compute copied nothing (GLES: empty draw commands) or stale garbage (Vulkan: wild indirect commands ending in VK_ERROR_DEVICE_LOST). - MG_Impl/MG_Backend: real glFenceSync objects backed by backend fences (GLES: native ES syncs guarded by context generation and owner thread; Vulkan: buffer-manager frame serials), replacing always-signaled stubs that let Flywheel reclaim staging memory the GPU still reads. - MG_Backend/DirectGLES: compute dispatches now run the same per-program resource sync as draws (uniform-block bindings and sampler units must be re-established through the API because layout(binding) is stripped from transpiled ESSL) and rebind texture units afterwards; the cull shader used to read a stale _FlwFrameUniforms binding and the depth-pyramid downsample sampled a stale unit-0 texture, zeroing the Hi-Z pyramid and occlusion-culling all Flywheel geometry. Image uniforms are excluded from glUniform1i (ES bakes their unit via layout(binding)); image-unit sync is clamped to the device limit; eliminated/SSBO-classified uniform blocks are skipped. - MG_Backend/DirectGLES: gl_BaseInstance in native indirect draws reads the GPU-written command buffer through an injected mg_IndirectParams SSBO view addressed per draw instead of the zero CPU shadow; layout(binding) is preserved for SSBO/image declarations (ES has no API rebinding for them); the ES context ownership claim moved to a global atomic owner thread with an EGL ground-truth check, and deferred buffer op state is mutex-guarded, so ops cannot silently no-op after context migration. - MG_Backend/DirectVulkan: new RebaseInstanceIndexPass rewrites vertex InstanceIndex loads to (InstanceIndex - BaseInstance). glslang's relaxed Vulkan mode aliases gl_InstanceID to InstanceIndex, which includes firstInstance, but GL's gl_InstanceID is zero-based - draws with nonzero baseInstance paired meshes with wrong instance data (cogwheel drawn as a waterwheel, another wheel collapsed invisible). Gated on the shaderDrawParameters device feature. Sampled-read barriers additionally cover the compute stage (the Hi-Z downsample samples the depth attachment from compute), and short uniform-buffer ranges keep the existing zero-padding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
38 lines
1.8 KiB
C++
38 lines
1.8 KiB
C++
// MobileGL - MobileGL/MG_Util/ShaderTranspiler/SpirvPasses/RebaseInstanceIndexPass.h
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#pragma once
|
|
#include "source/opt/pass.h"
|
|
#include "spirv-tools/optimizer.hpp"
|
|
|
|
#include <Includes.h>
|
|
|
|
namespace MobileGL {
|
|
namespace MG_Util {
|
|
namespace ShaderTranspiler {
|
|
// glslang's relaxed-Vulkan mode aliases GL's gl_InstanceID to Vulkan's
|
|
// gl_InstanceIndex. That is wrong for OpenGL semantics: GL's gl_InstanceID is
|
|
// zero-based (excludes baseInstance) while Vulkan's InstanceIndex includes the
|
|
// draw's firstInstance. On the DirectVulkan backend any draw with baseInstance != 0
|
|
// (Flywheel's glMultiDrawElementsIndirect, glDrawElementsInstancedBaseInstance)
|
|
// therefore feeds shaders an InstanceID offset by baseInstance. This pass rebases
|
|
// every load of the InstanceIndex builtin to (InstanceIndex - BaseInstance), the
|
|
// same lowering Zink/DXVK use, so the value seen by the shader matches GL's
|
|
// zero-based gl_InstanceID. Vulkan backend only - the DirectGLES transpile path
|
|
// already receives a zero-based gl_InstanceID from SPIRV-Cross.
|
|
class RebaseInstanceIndexPass : public spvtools::opt::Pass {
|
|
public:
|
|
const char* name() const override { return "rebase-instance-index"; }
|
|
Status Process() override;
|
|
|
|
static spvtools::Optimizer::PassToken CreateRebaseInstanceIndexPass();
|
|
};
|
|
} // namespace ShaderTranspiler
|
|
} // namespace MG_Util
|
|
} // namespace MobileGL
|