@@ -21,44 +21,28 @@ static const wgpu::TextureFormat PreferredTextureFormat =
2121 wgpu::TextureFormat::RGBA8Unorm;
2222#endif
2323
24- inline skgpu::graphite::DawnBackendContext
25- createDawnBackendContext (dawn::native::Instance *instance) {
26-
27- auto useTintIR = false ;
28- static constexpr const char *kToggles [] = {
29- #if !defined(SK_DEBUG)
30- " skip_validation" ,
31- #endif
32- " disable_lazy_clear_for_mapped_at_creation_buffer" ,
33- " allow_unsafe_apis" ,
34- " use_user_defined_labels_in_backend" ,
35- " disable_robustness" ,
36- " use_tint_ir" ,
37- };
38- wgpu::DawnTogglesDescriptor togglesDesc;
39- togglesDesc.enabledToggleCount = std::size (kToggles ) - (useTintIR ? 0 : 1 );
40- togglesDesc.enabledToggles = kToggles ;
41-
42- dawn::native::Adapter matchedAdaptor;
43-
44- wgpu::RequestAdapterOptions options;
24+ // Find the best matching GPU adapter for the current platform.
25+ // Sorts by adapter type (DiscreteGPU > IntegratedGPU > CPU) and selects the
26+ // first adapter matching the platform backend (Metal on Apple, Vulkan on
27+ // Android).
28+ inline dawn::native::Adapter
29+ getMatchedAdapter (dawn::native::Instance *instance) {
4530#ifdef __APPLE__
4631 constexpr auto kDefaultBackendType = wgpu::BackendType::Metal;
4732#elif __ANDROID__
4833 constexpr auto kDefaultBackendType = wgpu::BackendType::Vulkan;
4934#endif
35+
36+ wgpu::RequestAdapterOptions options;
5037 options.backendType = kDefaultBackendType ;
5138 options.featureLevel = wgpu::FeatureLevel::Core;
52- options.nextInChain = &togglesDesc;
5339
5440 std::vector<dawn::native::Adapter> adapters =
5541 instance->EnumerateAdapters (&options);
5642 if (adapters.empty ()) {
5743 throw std::runtime_error (" No matching adapter found" );
5844 }
5945
60- // Sort adapters by adapterType(DiscreteGPU, IntegratedGPU, CPU) and
61- // backendType(Metal, Vulkan, OpenGL, OpenGLES, WebGPU).
6246 std::sort (adapters.begin (), adapters.end (),
6347 [](dawn::native::Adapter a, dawn::native::Adapter b) {
6448 wgpu::Adapter wgpuA = a.Get ();
@@ -76,16 +60,93 @@ createDawnBackendContext(dawn::native::Instance *instance) {
7660 wgpu::AdapterInfo props;
7761 wgpuAdapter.GetInfo (&props);
7862 if (kDefaultBackendType == props.backendType ) {
79- matchedAdaptor = adapter;
80- break ;
63+ return adapter;
8164 }
8265 }
8366
84- if (!matchedAdaptor) {
85- throw std::runtime_error (" No matching adapter found" );
67+ throw std::runtime_error (" No matching adapter found" );
68+ }
69+
70+ // Create a Dawn device from the given adapter with the requested features.
71+ // Features not supported by the adapter are silently skipped.
72+ // Set fatalOnDeviceLost=true for primary rendering devices (SK_ABORT on loss),
73+ // false for secondary/compute devices (log only).
74+ inline wgpu::Device
75+ requestDevice (dawn::native::Adapter &nativeAdapter,
76+ const std::vector<wgpu::FeatureName> &requestedFeatures,
77+ bool fatalOnDeviceLost = true ) {
78+ wgpu::Adapter adapter = nativeAdapter.Get ();
79+
80+ // Filter to only features the adapter supports
81+ std::vector<wgpu::FeatureName> features;
82+ for (auto feature : requestedFeatures) {
83+ if (adapter.HasFeature (feature)) {
84+ features.push_back (feature);
85+ }
8686 }
8787
88- wgpu::Adapter adapter = matchedAdaptor.Get ();
88+ static constexpr const char *kToggles [] = {
89+ #if !defined(SK_DEBUG)
90+ " skip_validation" ,
91+ #endif
92+ " disable_lazy_clear_for_mapped_at_creation_buffer" ,
93+ " allow_unsafe_apis" ,
94+ " use_user_defined_labels_in_backend" ,
95+ " disable_robustness" ,
96+ };
97+ wgpu::DawnTogglesDescriptor togglesDesc;
98+ togglesDesc.enabledToggleCount = std::size (kToggles );
99+ togglesDesc.enabledToggles = kToggles ;
100+
101+ wgpu::DeviceDescriptor desc;
102+ desc.requiredFeatureCount = features.size ();
103+ desc.requiredFeatures = features.data ();
104+ desc.nextInChain = &togglesDesc;
105+
106+ if (fatalOnDeviceLost) {
107+ desc.SetDeviceLostCallback (
108+ wgpu::CallbackMode::AllowSpontaneous,
109+ [](const wgpu::Device &, wgpu::DeviceLostReason reason,
110+ wgpu::StringView message) {
111+ if (reason != wgpu::DeviceLostReason::Destroyed) {
112+ SK_ABORT (" Device lost: %.*s\n " ,
113+ static_cast <int >(message.length ), message.data );
114+ }
115+ });
116+ desc.SetUncapturedErrorCallback (
117+ [](const wgpu::Device &, wgpu::ErrorType,
118+ wgpu::StringView message) {
119+ SkDebugf (" Device error: %.*s\n " ,
120+ static_cast <int >(message.length ), message.data );
121+ });
122+ } else {
123+ desc.SetDeviceLostCallback (
124+ wgpu::CallbackMode::AllowSpontaneous,
125+ [](const wgpu::Device &, wgpu::DeviceLostReason reason,
126+ wgpu::StringView message) {
127+ if (reason != wgpu::DeviceLostReason::Destroyed) {
128+ RNSkia::RNSkLogger::logToConsole (
129+ " Device lost: %.*s" ,
130+ static_cast <int >(message.length ), message.data );
131+ }
132+ });
133+ desc.SetUncapturedErrorCallback (
134+ [](const wgpu::Device &, wgpu::ErrorType,
135+ wgpu::StringView message) {
136+ RNSkia::RNSkLogger::logToConsole (
137+ " Device error: %.*s" ,
138+ static_cast <int >(message.length ), message.data );
139+ });
140+ }
141+
142+ return wgpu::Device::Acquire (nativeAdapter.CreateDevice (&desc));
143+ }
144+
145+ inline skgpu::graphite::DawnBackendContext
146+ createDawnBackendContext (dawn::native::Instance *instance) {
147+
148+ auto matchedAdapter = getMatchedAdapter (instance);
149+ wgpu::Adapter adapter = matchedAdapter.Get ();
89150
90151 // Log selected adapter info
91152 wgpu::AdapterInfo adapterInfo;
@@ -130,93 +191,34 @@ createDawnBackendContext(dawn::native::Instance *instance) {
130191 " Selected Dawn adapter - Backend: %s, Device: %s, Description: %s" ,
131192 backendName.c_str (), deviceName.c_str (), description.c_str ());
132193
133- std::vector<wgpu::FeatureName> features;
134- if (adapter.HasFeature (wgpu::FeatureName::MSAARenderToSingleSampled)) {
135- features.push_back (wgpu::FeatureName::MSAARenderToSingleSampled);
136- }
137- if (adapter.HasFeature (wgpu::FeatureName::TransientAttachments)) {
138- features.push_back (wgpu::FeatureName::TransientAttachments);
139- }
140- if (adapter.HasFeature (wgpu::FeatureName::Unorm16TextureFormats)) {
141- features.push_back (wgpu::FeatureName::Unorm16TextureFormats);
142- }
143- if (adapter.HasFeature (wgpu::FeatureName::DualSourceBlending)) {
144- features.push_back (wgpu::FeatureName::DualSourceBlending);
145- }
146- if (adapter.HasFeature (wgpu::FeatureName::FramebufferFetch)) {
147- features.push_back (wgpu::FeatureName::FramebufferFetch);
148- }
149- if (adapter.HasFeature (wgpu::FeatureName::BufferMapExtendedUsages)) {
150- features.push_back (wgpu::FeatureName::BufferMapExtendedUsages);
151- }
152- if (adapter.HasFeature (wgpu::FeatureName::TextureCompressionETC2)) {
153- features.push_back (wgpu::FeatureName::TextureCompressionETC2);
154- }
155- if (adapter.HasFeature (wgpu::FeatureName::TextureCompressionBC)) {
156- features.push_back (wgpu::FeatureName::TextureCompressionBC);
157- }
158- if (adapter.HasFeature (wgpu::FeatureName::R8UnormStorage)) {
159- features.push_back (wgpu::FeatureName::R8UnormStorage);
160- }
161- if (adapter.HasFeature (wgpu::FeatureName::DawnLoadResolveTexture)) {
162- features.push_back (wgpu::FeatureName::DawnLoadResolveTexture);
163- }
164- if (adapter.HasFeature (wgpu::FeatureName::DawnPartialLoadResolveTexture)) {
165- features.push_back (wgpu::FeatureName::DawnPartialLoadResolveTexture);
166- }
167- if (adapter.HasFeature (wgpu::FeatureName::TimestampQuery)) {
168- features.push_back (wgpu::FeatureName::TimestampQuery);
169- }
170- if (adapter.HasFeature (wgpu::FeatureName::DawnTexelCopyBufferRowAlignment)) {
171- features.push_back (wgpu::FeatureName::DawnTexelCopyBufferRowAlignment);
172- }
173- if (adapter.HasFeature (wgpu::FeatureName::ImplicitDeviceSynchronization)) {
174- features.push_back (wgpu::FeatureName::ImplicitDeviceSynchronization);
175- }
194+ // Primary device features — request everything Skia/Graphite can use
195+ std::vector<wgpu::FeatureName> features = {
196+ wgpu::FeatureName::MSAARenderToSingleSampled,
197+ wgpu::FeatureName::TransientAttachments,
198+ wgpu::FeatureName::Unorm16TextureFormats,
199+ wgpu::FeatureName::DualSourceBlending,
200+ wgpu::FeatureName::FramebufferFetch,
201+ wgpu::FeatureName::BufferMapExtendedUsages,
202+ wgpu::FeatureName::TextureCompressionETC2,
203+ wgpu::FeatureName::TextureCompressionBC,
204+ wgpu::FeatureName::R8UnormStorage,
205+ wgpu::FeatureName::DawnLoadResolveTexture,
206+ wgpu::FeatureName::DawnPartialLoadResolveTexture,
207+ wgpu::FeatureName::TimestampQuery,
208+ wgpu::FeatureName::DawnTexelCopyBufferRowAlignment,
209+ wgpu::FeatureName::ImplicitDeviceSynchronization,
176210#ifdef __APPLE__
177- if (adapter.HasFeature (wgpu::FeatureName::SharedTextureMemoryIOSurface)) {
178- features.push_back (wgpu::FeatureName::SharedTextureMemoryIOSurface);
179- }
180- if (adapter.HasFeature (wgpu::FeatureName::DawnMultiPlanarFormats)) {
181- features.push_back (wgpu::FeatureName::DawnMultiPlanarFormats);
182- }
183- if (adapter.HasFeature (wgpu::FeatureName::MultiPlanarFormatP010)) {
184- features.push_back (wgpu::FeatureName::MultiPlanarFormatP010);
185- }
186- if (adapter.HasFeature (wgpu::FeatureName::MultiPlanarFormatP210)) {
187- features.push_back (wgpu::FeatureName::MultiPlanarFormatP210);
188- }
189- if (adapter.HasFeature (wgpu::FeatureName::MultiPlanarFormatExtendedUsages)) {
190- features.push_back (wgpu::FeatureName::MultiPlanarFormatExtendedUsages);
191- }
211+ wgpu::FeatureName::SharedTextureMemoryIOSurface,
212+ wgpu::FeatureName::DawnMultiPlanarFormats,
213+ wgpu::FeatureName::MultiPlanarFormatP010,
214+ wgpu::FeatureName::MultiPlanarFormatP210,
215+ wgpu::FeatureName::MultiPlanarFormatExtendedUsages,
192216#else
193- if (adapter.HasFeature (
194- wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) {
195- features.push_back (wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer);
196- }
217+ wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer,
197218#endif
219+ };
198220
199- wgpu::DeviceDescriptor desc;
200- desc.requiredFeatureCount = features.size ();
201- desc.requiredFeatures = features.data ();
202- desc.nextInChain = &togglesDesc;
203- desc.SetDeviceLostCallback (
204- wgpu::CallbackMode::AllowSpontaneous,
205- [](const wgpu::Device &, wgpu::DeviceLostReason reason,
206- wgpu::StringView message) {
207- if (reason != wgpu::DeviceLostReason::Destroyed) {
208- SK_ABORT (" Device lost: %.*s\n " , static_cast <int >(message.length ),
209- message.data );
210- }
211- });
212- desc.SetUncapturedErrorCallback (
213- [](const wgpu::Device &, wgpu::ErrorType, wgpu::StringView message) {
214- SkDebugf (" Device error: %.*s\n " , static_cast <int >(message.length ),
215- message.data );
216- });
217-
218- wgpu::Device device =
219- wgpu::Device::Acquire (matchedAdaptor.CreateDevice (&desc));
221+ wgpu::Device device = requestDevice (matchedAdapter, features, true );
220222 SkASSERT (device);
221223
222224 skgpu::graphite::DawnBackendContext backendContext;
@@ -227,4 +229,4 @@ createDawnBackendContext(dawn::native::Instance *instance) {
227229 return backendContext;
228230}
229231
230- } // namespace DawnUtils
232+ } // namespace DawnUtils
0 commit comments