Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GraphiteDawnTestContext.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
18
19#include "dawn/dawn_proc.h"
20
21#define LOG_ADAPTER 0
22
23namespace skiatest::graphite {
24
25// TODO: http://crbug.com/dawn/2450 - Currently manually setting the device to null and calling
26// tick/process events one last time to ensure that the device is lost accordingly at
27// destruction. Once device lost is, by default, a spontaneous event, remove this.
32
33std::unique_ptr<GraphiteTestContext> DawnTestContext::Make(wgpu::BackendType backend) {
34 static std::unique_ptr<dawn::native::Instance> sInstance;
35 static SkOnce sOnce;
36
37 static constexpr const char* kToggles[] = {
38 "allow_unsafe_apis", // Needed for dual-source blending.
39 "use_user_defined_labels_in_backend",
40 };
41 wgpu::DawnTogglesDescriptor togglesDesc;
42 togglesDesc.enabledToggleCount = std::size(kToggles);
43 togglesDesc.enabledToggles = kToggles;
44
45 // Creation of Instance is cheap but calling EnumerateAdapters can be expensive the first time,
46 // but then the results are cached on the Instance object. So save the Instance here so we can
47 // avoid the overhead of EnumerateAdapters on every test.
48 sOnce([&]{
49 DawnProcTable backendProcs = dawn::native::GetProcs();
50 dawnProcSetProcs(&backendProcs);
51 WGPUInstanceDescriptor desc{};
52 // need for WaitAny with timeout > 0
53 desc.features.timedWaitAnyEnable = true;
54 sInstance = std::make_unique<dawn::native::Instance>(&desc);
55 });
56
57 dawn::native::Adapter matchedAdaptor;
58
59 wgpu::RequestAdapterOptions options;
60 options.nextInChain = &togglesDesc;
61 std::vector<dawn::native::Adapter> adapters = sInstance->EnumerateAdapters(&options);
62 SkASSERT(!adapters.empty());
63 // Sort adapters by adapterType(DiscreteGPU, IntegratedGPU, CPU) and
64 // backendType(WebGPU, D3D11, D3D12, Metal, Vulkan, OpenGL, OpenGLES).
65 std::sort(adapters.begin(),
66 adapters.end(),
67 [](dawn::native::Adapter a, dawn::native::Adapter b) {
68 wgpu::AdapterProperties propA;
69 wgpu::AdapterProperties propB;
70 a.GetProperties(&propA);
71 b.GetProperties(&propB);
72 return std::tuple(propA.adapterType, propA.backendType) <
73 std::tuple(propB.adapterType, propB.backendType);
74 });
75
76 for (const auto& adapter : adapters) {
77 wgpu::AdapterProperties props;
78 adapter.GetProperties(&props);
79 if (backend == props.backendType) {
80 matchedAdaptor = adapter;
81 break;
82 }
83 }
84
85 if (!matchedAdaptor) {
86 return nullptr;
87 }
88
89#if LOG_ADAPTER
90 wgpu::AdapterProperties properties;
91 sAdapter.GetProperties(&properties);
92 SkDebugf("GPU: %s\nDriver: %s\n", properties.name, properties.driverDescription);
93#endif
94
95 std::vector<wgpu::FeatureName> features;
96 wgpu::Adapter adapter = matchedAdaptor.Get();
97 if (adapter.HasFeature(wgpu::FeatureName::MSAARenderToSingleSampled)) {
98 features.push_back(wgpu::FeatureName::MSAARenderToSingleSampled);
99 }
100 if (adapter.HasFeature(wgpu::FeatureName::TransientAttachments)) {
101 features.push_back(wgpu::FeatureName::TransientAttachments);
102 }
103 if (adapter.HasFeature(wgpu::FeatureName::Unorm16TextureFormats)) {
104 features.push_back(wgpu::FeatureName::Unorm16TextureFormats);
105 }
106 if (adapter.HasFeature(wgpu::FeatureName::DualSourceBlending)) {
107 features.push_back(wgpu::FeatureName::DualSourceBlending);
108 }
109 if (adapter.HasFeature(wgpu::FeatureName::FramebufferFetch)) {
110 features.push_back(wgpu::FeatureName::FramebufferFetch);
111 }
112 if (adapter.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages)) {
113 features.push_back(wgpu::FeatureName::BufferMapExtendedUsages);
114 }
115 if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionETC2)) {
116 features.push_back(wgpu::FeatureName::TextureCompressionETC2);
117 }
118 if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionBC)) {
119 features.push_back(wgpu::FeatureName::TextureCompressionBC);
120 }
121 if (adapter.HasFeature(wgpu::FeatureName::R8UnormStorage)) {
122 features.push_back(wgpu::FeatureName::R8UnormStorage);
123 }
124
125 wgpu::DeviceDescriptor desc;
126 desc.requiredFeatureCount = features.size();
127 desc.requiredFeatures = features.data();
128 desc.nextInChain = &togglesDesc;
129
130 wgpu::Device device = wgpu::Device::Acquire(matchedAdaptor.CreateDevice(&desc));
132 device.SetUncapturedErrorCallback(
133 [](WGPUErrorType type, const char* message, void*) {
134 SkDebugf("Device error: %s\n", message);
135 },
136 /*userdata=*/nullptr);
137 device.SetDeviceLostCallback(
138 [](WGPUDeviceLostReason reason, const char* message, void*) {
139 if (reason != WGPUDeviceLostReason_Destroyed) {
140 SK_ABORT("Device lost: %s\n", message);
141 }
142 },
143 /*userdata=*/nullptr);
144
146 backendContext.fInstance = wgpu::Instance(sInstance->Get());
147 backendContext.fDevice = device;
148 backendContext.fQueue = device.GetQueue();
149 return std::unique_ptr<GraphiteTestContext>(new DawnTestContext(backendContext));
150}
151
153 wgpu::AdapterProperties props;
154 fBackendContext.fDevice.GetAdapter().GetProperties(&props);
155 switch (props.backendType) {
156 case wgpu::BackendType::D3D11:
157 return skgpu::ContextType::kDawn_D3D11;
158
159 case wgpu::BackendType::D3D12:
160 return skgpu::ContextType::kDawn_D3D12;
161
162 case wgpu::BackendType::Metal:
163 return skgpu::ContextType::kDawn_Metal;
164
165 case wgpu::BackendType::Vulkan:
166 return skgpu::ContextType::kDawn_Vulkan;
167
168 case wgpu::BackendType::OpenGL:
169 return skgpu::ContextType::kDawn_OpenGL;
170
171 case wgpu::BackendType::OpenGLES:
172 return skgpu::ContextType::kDawn_OpenGLES;
173 default:
174 SK_ABORT("unexpected Dawn backend");
175 return skgpu::ContextType::kMock;
176 }
177}
178
179std::unique_ptr<skgpu::graphite::Context> DawnTestContext::makeContext(const TestOptions& options) {
180 skgpu::graphite::ContextOptions revisedContextOptions(options.fContextOptions);
181 skgpu::graphite::ContextOptionsPriv contextOptionsPriv;
182 if (!options.fContextOptions.fOptionsPriv) {
183 revisedContextOptions.fOptionsPriv = &contextOptionsPriv;
184 }
185 // Needed to make synchronous readPixels work
186 revisedContextOptions.fOptionsPriv->fStoreContextRefInRecorder = true;
187
188 auto backendContext = fBackendContext;
189 if (options.fNeverYieldToWebGPU) {
190 backendContext.fTick = nullptr;
191 }
192
193 return skgpu::graphite::ContextFactory::MakeDawn(backendContext, revisedContextOptions);
194}
195
197
198} // namespace skiatest::graphite
const char * options
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkASSERT(cond)
Definition SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
skgpu::graphite::DawnBackendContext fBackendContext
static std::unique_ptr< GraphiteTestContext > Make(wgpu::BackendType backend)
std::unique_ptr< skgpu::graphite::Context > makeContext(const TestOptions &) override
VkDevice device
Definition main.cc:53
static bool b
struct MyStruct a[10]
Win32Message message
SK_API std::unique_ptr< Context > MakeDawn(const DawnBackendContext &, const ContextOptions &)
ContextOptionsPriv * fOptionsPriv