Skip to content

Expose Skia's Vulkan device-lost callback (#4601) - #338

Open
ramezgerges wants to merge 1 commit into
mono:skiasharpfrom
ramezgerges:dev/issue-4601-vulkan-device-lost-callback
Open

Expose Skia's Vulkan device-lost callback (#4601)#338
ramezgerges wants to merge 1 commit into
mono:skiasharpfrom
ramezgerges:dev/issue-4601-vulkan-device-lost-callback

Conversation

@ramezgerges

@ramezgerges ramezgerges commented Aug 4, 2026

Copy link
Copy Markdown

Description

Exposes Skia's Vulkan device-lost callback (skgpu::VulkanBackendContext.fDeviceLostContext / fDeviceLostProc) on the C API so managed callers can react to VK_ERROR_DEVICE_LOST — the intended channel for detecting TDRs / driver resets.

Skia's own callback signature is (std::string description, std::vector<VkDeviceFaultAddressInfoEXT>, std::vector<VkDeviceFaultVendorInfoEXT>, std::vector<std::byte>). Not C-ABI-friendly. The shim adapts it into a gr_vk_device_lost_info_t POD struct that mirrors the full payload — description string + address-info array + vendor-info array + vendor binary blob. The Vk struct layouts are stable ABI, so the shim's gr_vk_device_fault_*_info_t mirror them field-for-field and reinterpret_cast the vector storage (no per-element copy). Static_assert guards the layout equivalence.

Same caller-owned bridge pattern as sk_graphite_shader_error_handler (_new returns an opaque handle; caller passes to backend context; caller deletes after Context destruction). No leaks.

SkiaSharp issue

Related to mono/SkiaSharp#4601

Required SkiaSharp PR

Requires mono/SkiaSharp#4655

Areas affected

  • C API (include/c, src/c)
  • Native dependency / DEPS
  • Build (gn / build files)
  • Upstream Skia merge or rebase
  • Rendering output / behavior
  • Other

Changes

C API

// New POD structs (mirror VkDeviceFault*InfoEXT layouts verbatim)
typedef struct { int32_t fAddressType; uint64_t fReportedAddress; uint64_t fAddressPrecision; } gr_vk_device_fault_address_info_t;
typedef struct { char fDescription[256]; uint64_t fVendorFaultCode; uint64_t fVendorFaultData; } gr_vk_device_fault_vendor_info_t;

typedef struct {
    const char* fDescription;
    const gr_vk_device_fault_address_info_t* fAddressInfos;  int32_t fAddressInfoCount;
    const gr_vk_device_fault_vendor_info_t*  fVendorInfos;   int32_t fVendorInfoCount;
    const void* fVendorBinaryData;                            size_t  fVendorBinaryDataSize;
} gr_vk_device_lost_info_t;

typedef void (*gr_vk_device_lost_proc)(void* userData, const gr_vk_device_lost_info_t* info);
typedef struct gr_vk_device_lost_handler_t gr_vk_device_lost_handler_t;

gr_vk_device_lost_handler_t* gr_vk_device_lost_handler_new(gr_vk_device_lost_proc proc, void* userData);
void                         gr_vk_device_lost_handler_delete(gr_vk_device_lost_handler_t* handler);

// gr_vk_backendcontext_t + sk_graphite_vk_backend_context_init_t both gain:
gr_vk_device_lost_handler_t* fDeviceLostHandler;   // nullable

Behavior

  • Ganesh Vulkan + Graphite Vulkan callers who set fDeviceLostHandler now receive Skia's full device-lost payload on the driver-owned thread — description + address-info array + vendor-info array + vendor binary blob (the last three empty when VK_EXT_device_fault isn't enabled).
  • Callers who leave fDeviceLostHandler null get today's behavior (no callback).
  • No behavior change for existing null-slot callers.

Testing

Verified in the companion SkiaSharp PR: 5 proxy-level marshalling tests + 5 Vulkan integration tests. All pass locally on Linux/Lavapipe alongside the full Vulkan regression suite (28 pass / 2 skip / 0 fail).

Actually forcing VK_ERROR_DEVICE_LOST in CI isn't realistic (needs hardware TDR); the proxy tests cover the marshalling, the integration tests cover the wiring.

Checklist

  • Targets the skiasharp branch
  • Changes above lists every added/changed C API export (or "None.")
  • Companion mono/SkiaSharp PR linked above (submodule bump at minimum; regenerates bindings + adds tests for C API changes)

Skia's skgpu::VulkanBackendContext gained fDeviceLostContext /
fDeviceLostProc after the milestone we last mapped this struct against.
On VK_ERROR_DEVICE_LOST Skia invokes the callback with driver-provided
fault text (from VK_EXT_device_fault when the extension is enabled) —
the intended channel for apps to react to TDRs / driver resets. Until
now the C shim didn't expose it, so managed callers had no way to see
device-loss events.

* new gr_vk_device_lost.h / .cpp — opaque handle,
  gr_vk_device_lost_handler_new(proc, userData) /
  gr_vk_device_lost_handler_delete(handle). Bridge adapts Skia's beefy
  callback signature (std::string + VkDeviceFaultAddressInfoEXT /
  VendorInfo vectors) down to a plain C proc that takes only the
  description. v1 drops the fault-detail arrays; a fault-details
  overload can land later if a customer needs them.
* gr_vk_backendcontext_t and sk_graphite_vk_backend_context_init_t
  gain fDeviceLostHandler. Nullable, caller-owned; the C shim installs
  the bridge on skgpu::VulkanBackendContext non-owning so the handle
  must outlive the Context.
* AsGrVkBackendContext + sk_graphite_context_make_vulkan wire the
  handle through to Skia's fDeviceLostContext / fDeviceLostProc.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ramezgerges
ramezgerges force-pushed the dev/issue-4601-vulkan-device-lost-callback branch from 61a61ac to 482d44c Compare August 4, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant