[Fix] (DirectVulkan): rewrite implicit-LOD fragment samples to explicit LOD 0 when every bound sampler is pinned to a single mip level - Adreno 650 (driver 512.502) reads outside a full-screen colour render target's allocation on its implicit-LOD sampling path and faults the GPU, which killed MC 26.2 on its own blit shader (texture(InSampler, texCoord)) between frames 344-421 on every run; this is the same driver defect the default-framebuffer blit shader already works around with textureLod, but an application's shader cannot be edited, so ForceExplicitLod0SamplePass converts OpImageSample*ImplicitLod to the explicit form at the SPIR-V level under a new CompileOptionBit that is only requested when the rewrite provably cannot move a texel (every sampler binding on a single-level view, no anisotropy, and either a LOD clamp that already pins lambda at 0 or min and mag filters that agree - an explicit LOD 0 always takes the magnification side of the min/mag decision); a single-level view now also clamps its sampler to mipmapMode NEAREST with maxLod min(maxLod, 0.25) rather than 0, since collapsing the clamp would make every fragment magnify and quietly retire the min filter; and the program's backend hash memo grows from one slot to four so a program resolved under two compile-flag sets in the same frame stops re-hashing every stage's SPIR-V once per draw

This commit is contained in:
2026-07-29 03:26:57 -04:00
parent 0ea9e6de5f
commit 992d16267c
8 changed files with 356 additions and 25 deletions
@@ -4267,7 +4267,16 @@ void main() {
const auto& vao = *MG_State::pGLContext->GetBoundVertexArray();
const auto& program = *MG_State::pGLContext->GetCurrentProgram();
ProgramFactory::CompileOptionFlags transformFlags = GetShaderTransformFlags(m_swapchainObject.GetPreTransform());
const auto& programObj = m_programFactory->GetOrCreateProgram(program, transformFlags);
const auto* programObjPtr = &m_programFactory->GetOrCreateProgram(program, transformFlags);
// Sampling a colour render target through the driver's implicit-LOD path faults the GPU on
// Adreno 650 (see ForceExplicitLod0SamplePass); ask for the explicit-LOD variant when doing
// so cannot change a texel, i.e. when every sampler this program reads is pinned to a
// single mip level.
if (UniformManager::ProgramSamplesOnlySingleLevelTextures(program, *programObjPtr)) {
transformFlags |= ProgramFactory::CompileOptionBit::ExplicitLod0Sampling;
programObjPtr = &m_programFactory->GetOrCreateProgram(program, transformFlags);
}
const auto& programObj = *programObjPtr;
// Begin command recording if not yet
if (!frame.isCommandRecording) {