fix(device): preferred mask + required-only fallback for GetMemoryType (#59) #87

Merged
catbot merged 1 commit from claude/issue-59 into master 2026-06-16 18:04:21 +02:00
Member

Summary

Device::GetMemoryType was a bare first-superset match with no fallback — it threw whenever no memory type satisfied the requested property flags. Callers that combine a mandatory flag with a perf-only one (the descriptor heaps request HOST_VISIBLE | DEVICE_LOCAL) would then fail allocation on any device without a host-visible device-local heap (i.e. no resizable BAR).

The fix adds a preferred mask distinct from required:

  • a type satisfying required | preferred is chosen first;
  • if none exists, it falls back to a required-only match instead of throwing;
  • it throws only when even required cannot be met (no valid memory exists for the allocation).

VulkanBuffer::Create/Resize gain an optional trailing preferredPropertyFlags (defaulted, source-compatible), and the descriptor heaps now treat DEVICE_LOCAL as a preference layered on mandatory HOST_VISIBLE. On resizable-BAR hardware the first-pass match is unchanged; non-ReBAR hardware now gets a host-visible-only allocation rather than a hard failure.

Correctness note

This change deliberately does not touch any flush/barrier behaviour. No coherency is assumed anywhere here — FlushDevice and its mandatory HOST_WRITE→device barrier are untouched.

Tests

Adds tests/MemoryTypeFallback, a pure-CPU test (no GPU device needed) that installs synthetic Device::memoryProperties layouts and exercises:

  • required-only first-superset selection and typeBits gating
  • preferred bits honoured when available (incl. skipping an earlier required-only type)
  • unsatisfiable preference falling back to required-only without throwing
  • unsatisfiable required still throwing

crafter-build test7 passed (MemoryTypeFallback + the 6 existing tests).

Resolves #59

## Summary `Device::GetMemoryType` was a bare first-superset match with **no fallback** — it threw whenever no memory type satisfied the requested property flags. Callers that combine a mandatory flag with a perf-only one (the descriptor heaps request `HOST_VISIBLE | DEVICE_LOCAL`) would then fail allocation on any device without a host-visible device-local heap (i.e. no resizable BAR). The fix adds a `preferred` mask distinct from `required`: - a type satisfying `required | preferred` is chosen first; - if none exists, it falls back to a `required`-only match instead of throwing; - it throws only when even `required` cannot be met (no valid memory exists for the allocation). `VulkanBuffer::Create`/`Resize` gain an optional trailing `preferredPropertyFlags` (defaulted, source-compatible), and the descriptor heaps now treat `DEVICE_LOCAL` as a preference layered on mandatory `HOST_VISIBLE`. On resizable-BAR hardware the first-pass match is unchanged; non-ReBAR hardware now gets a host-visible-only allocation rather than a hard failure. ### Correctness note This change deliberately does **not** touch any flush/barrier behaviour. No coherency is assumed anywhere here — `FlushDevice` and its mandatory `HOST_WRITE`→device barrier are untouched. ## Tests Adds `tests/MemoryTypeFallback`, a pure-CPU test (no GPU device needed) that installs synthetic `Device::memoryProperties` layouts and exercises: - required-only first-superset selection and `typeBits` gating - preferred bits honoured when available (incl. skipping an earlier required-only type) - unsatisfiable preference falling back to required-only without throwing - unsatisfiable `required` still throwing `crafter-build test` → **7 passed** (MemoryTypeFallback + the 6 existing tests). Resolves #59
GetMemoryType was a bare first-superset match that threw whenever no
memory type satisfied the requested property flags. Callers combining a
mandatory flag with a perf-only one (HOST_VISIBLE | DEVICE_LOCAL for the
descriptor heaps) would then fail allocation on any device without a
host-visible device-local heap (no resizable BAR).

It now takes a `preferred` mask distinct from `required`: a type
satisfying both is chosen first, falling back to a required-only match
when the preference is unavailable, and throwing only when even
`required` cannot be met. VulkanBuffer::Create/Resize gain an optional
trailing `preferredPropertyFlags`, and the descriptor heaps now treat
DEVICE_LOCAL as a preference on top of mandatory HOST_VISIBLE.

This does not touch any flush/barrier behaviour — coherency is not
assumed anywhere here.

Adds tests/MemoryTypeFallback, a pure-CPU test that installs synthetic
memory layouts and exercises selection, preference, fallback, and the
unsatisfiable-required throw.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
catbot merged commit c58b68ec40 into master 2026-06-16 18:04:21 +02:00
catbot deleted branch claude/issue-59 2026-06-16 18:04:21 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Catcrafts/Crafter.Graphics!87
No description provided.