mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 00:03:45 +00:00
fix(gpu): drop the in-process-gpu tier from the fallback ladder
--in-process-gpu removes the GPU child entirely, but it also turns a recoverable child fault into a main-process kill. Nothing in the crash evidence says tier 2 is insufficient, so the strongest rung was risk without support. Ladder is now 1 -> 2.
This commit is contained in:
@@ -51,8 +51,8 @@ describe('gpu-fallback-marker', () => {
|
||||
|
||||
it('overwrites an existing marker when escalating tiers', () => {
|
||||
writeGpuFallbackMarker(userDataPath, { engagedAt: 1, crashesInWindow: 3, tier: 1 }, environment)
|
||||
writeGpuFallbackMarker(userDataPath, { engagedAt: 2, crashesInWindow: 4, tier: 3 }, environment)
|
||||
expect(readGpuFallbackMarker(userDataPath)?.tier).toBe(3)
|
||||
writeGpuFallbackMarker(userDataPath, { engagedAt: 2, crashesInWindow: 4, tier: 2 }, environment)
|
||||
expect(readGpuFallbackMarker(userDataPath)?.tier).toBe(2)
|
||||
})
|
||||
|
||||
it('returns null when no marker exists', () => {
|
||||
@@ -90,7 +90,7 @@ describe('gpu-fallback-marker', () => {
|
||||
platform: 'win32'
|
||||
})
|
||||
)
|
||||
expect(readGpuFallbackMarker(userDataPath)?.tier).toBe(3)
|
||||
expect(readGpuFallbackMarker(userDataPath)?.tier).toBe(2)
|
||||
})
|
||||
|
||||
it('defaults a marker with no tier to the first rung', () => {
|
||||
|
||||
@@ -11,8 +11,7 @@ describe('gpu-fallback-tiers', () => {
|
||||
it('escalates one rung at a time and stops at the top', () => {
|
||||
expect(getNextGpuFallbackTier(0)).toBe(1)
|
||||
expect(getNextGpuFallbackTier(1)).toBe(2)
|
||||
expect(getNextGpuFallbackTier(2)).toBe(3)
|
||||
expect(getNextGpuFallbackTier(3)).toBeNull()
|
||||
expect(getNextGpuFallbackTier(2)).toBeNull()
|
||||
})
|
||||
|
||||
// Why: null is what bounds relaunches per build; a non-null answer here is a crash loop.
|
||||
@@ -35,30 +34,32 @@ describe('gpu-fallback-tiers', () => {
|
||||
it('identifies ladder members', () => {
|
||||
expect(isGpuFallbackTier(1)).toBe(true)
|
||||
expect(isGpuFallbackTier(0)).toBe(false)
|
||||
expect(isGpuFallbackTier(4)).toBe(false)
|
||||
expect(isGpuFallbackTier(3)).toBe(false)
|
||||
})
|
||||
|
||||
// Why: escalating must never drop a switch a lower tier already needed.
|
||||
it('is additive across tiers', () => {
|
||||
const names = ([1, 2, 3] as const).map(
|
||||
(tier) => new Set(getGpuFallbackTierSwitches(tier).map((entry) => entry.name))
|
||||
)
|
||||
for (const name of names[0]) {
|
||||
expect(names[1].has(name)).toBe(true)
|
||||
}
|
||||
for (const name of names[1]) {
|
||||
expect(names[2].has(name)).toBe(true)
|
||||
const tier1 = new Set(getGpuFallbackTierSwitches(1).map((entry) => entry.name))
|
||||
const tier2 = new Set(getGpuFallbackTierSwitches(2).map((entry) => entry.name))
|
||||
for (const name of tier1) {
|
||||
expect(tier2.has(name)).toBe(true)
|
||||
}
|
||||
})
|
||||
|
||||
it('removes the GPU child process at the top tier', () => {
|
||||
const tier1 = getGpuFallbackTierSwitches(1).map((entry) => entry.name)
|
||||
expect(tier1).toEqual(['disable-gpu'])
|
||||
it('takes the compositor off the GPU child and ANGLE off the vendor driver at tier 2', () => {
|
||||
expect(getGpuFallbackTierSwitches(1).map((entry) => entry.name)).toEqual(['disable-gpu'])
|
||||
|
||||
const tier2 = getGpuFallbackTierSwitches(2)
|
||||
expect(tier2.map((entry) => entry.name)).toContain('disable-gpu-compositing')
|
||||
expect(tier2.find((entry) => entry.name === 'use-angle')?.value).toBe('swiftshader')
|
||||
})
|
||||
|
||||
expect(getGpuFallbackTierSwitches(3).map((entry) => entry.name)).toContain('in-process-gpu')
|
||||
// Why: in-process-gpu turns a recoverable child fault into a main-process kill.
|
||||
it('never offers in-process-gpu on any rung', () => {
|
||||
for (const tier of [1, 2] as const) {
|
||||
expect(getGpuFallbackTierSwitches(tier).map((entry) => entry.name)).not.toContain(
|
||||
'in-process-gpu'
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,20 +3,24 @@
|
||||
*
|
||||
* `--disable-gpu` alone does not stop Chromium from spawning a GPU child for the
|
||||
* Viz display compositor, so a driver that CHECK-crashes at GPU init keeps
|
||||
* killing every launch even with the fallback applied. Each tier removes
|
||||
* strictly more of the GPU process from the path; tier 3 removes the child
|
||||
* process entirely, which is the only shape a GPU-init crash cannot survive.
|
||||
* killing every launch even with the fallback applied (20 of 21 crashed launches
|
||||
* in the reported bundle already carried tier 1). Tier 2 takes the compositor off
|
||||
* the GPU child and forces ANGLE onto SwiftShader so the vendor DLL is never loaded.
|
||||
*
|
||||
* The ladder deliberately stops there. `--in-process-gpu` would remove the child
|
||||
* entirely, but it also turns a recoverable child fault into a main-process kill,
|
||||
* and nothing in the evidence says tier 2 is insufficient.
|
||||
*
|
||||
* Tiers are additive on purpose: escalating never drops a switch that a lower
|
||||
* tier already needed.
|
||||
*/
|
||||
|
||||
export const GPU_FALLBACK_TIERS = [1, 2, 3] as const
|
||||
export const GPU_FALLBACK_TIERS = [1, 2] as const
|
||||
|
||||
export type GpuFallbackTier = (typeof GPU_FALLBACK_TIERS)[number]
|
||||
|
||||
export const MIN_GPU_FALLBACK_TIER: GpuFallbackTier = 1
|
||||
export const MAX_GPU_FALLBACK_TIER: GpuFallbackTier = 3
|
||||
export const MAX_GPU_FALLBACK_TIER: GpuFallbackTier = 2
|
||||
|
||||
/** Tier 0 means "no fallback applied to this launch". */
|
||||
export const NO_GPU_FALLBACK_TIER = 0
|
||||
@@ -31,13 +35,6 @@ const TIER_SWITCHES: Record<GpuFallbackTier, readonly GpuFallbackSwitch[]> = {
|
||||
{ name: 'disable-gpu-compositing' },
|
||||
// Why: keeps a broken vendor D3D11 driver DLL out of the process even when Chromium still initializes ANGLE.
|
||||
{ name: 'use-angle', value: 'swiftshader' }
|
||||
],
|
||||
3: [
|
||||
{ name: 'disable-gpu' },
|
||||
{ name: 'disable-gpu-compositing' },
|
||||
{ name: 'use-angle', value: 'swiftshader' },
|
||||
// Why: last resort — no GPU child exists, so a GPU-init CHECK crash can no longer loop the app.
|
||||
{ name: 'in-process-gpu' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -63,7 +60,7 @@ export function getGpuFallbackTierSwitches(tier: GpuFallbackTier): readonly GpuF
|
||||
|
||||
/**
|
||||
* Next rung above `currentTier` (0 = nothing applied yet), or null once the
|
||||
* ladder is exhausted. Null is what bounds relaunches to 3 per build.
|
||||
* ladder is exhausted. Null is what bounds relaunches per build.
|
||||
*/
|
||||
export function getNextGpuFallbackTier(currentTier: number): GpuFallbackTier | null {
|
||||
if (Number.isNaN(currentTier) || currentTier < MIN_GPU_FALLBACK_TIER) {
|
||||
|
||||
Reference in New Issue
Block a user