1 /*
2 * Copyright 2022 Google Inc.
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
8 #include "tools/sk_app/GraphiteDawnWindowContext.h"
9
10 #include "include/core/SkSurface.h"
11 #include "include/gpu/graphite/BackendTexture.h"
12 #include "include/gpu/graphite/Context.h"
13 #include "include/gpu/graphite/ContextOptions.h"
14 #include "include/gpu/graphite/GraphiteTypes.h"
15 #include "include/gpu/graphite/Recorder.h"
16 #include "include/gpu/graphite/Recording.h"
17 #include "include/gpu/graphite/dawn/DawnBackendContext.h"
18 #include "include/gpu/graphite/dawn/DawnUtils.h"
19 #include "tools/ToolUtils.h"
20
21 #include "dawn/dawn_proc.h"
22
23 namespace sk_app {
24
GraphiteDawnWindowContext(const DisplayParams & params,wgpu::TextureFormat swapChainFormat)25 GraphiteDawnWindowContext::GraphiteDawnWindowContext(const DisplayParams& params,
26 wgpu::TextureFormat swapChainFormat)
27 : WindowContext(params)
28 , fSwapChainFormat(swapChainFormat)
29 , fInstance(std::make_unique<dawn::native::Instance>()) {
30 }
31
initializeContext(int width,int height)32 void GraphiteDawnWindowContext::initializeContext(int width, int height) {
33 SkASSERT(!fContext);
34
35 fWidth = width;
36 fHeight = height;
37
38 if (!onInitializeContext())
39 return;
40
41 SkASSERT(fDevice);
42 SkASSERT(fSurface);
43 SkASSERT(fSwapChain);
44
45 skgpu::graphite::DawnBackendContext backendContext;
46 backendContext.fDevice = fDevice;
47 backendContext.fQueue = fDevice.GetQueue();
48 skgpu::graphite::ContextOptions contextOptions;
49 contextOptions.fStoreContextRefInRecorder = true; // Needed to make synchronous readPixels work
50 fGraphiteContext = skgpu::graphite::ContextFactory::MakeDawn(backendContext,
51 contextOptions);
52 if (!fGraphiteContext) {
53 SkASSERT(false);
54 return;
55 }
56
57 fGraphiteRecorder = fGraphiteContext->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
58 SkASSERT(fGraphiteRecorder);
59 }
60
61 GraphiteDawnWindowContext::~GraphiteDawnWindowContext() = default;
62
destroyContext()63 void GraphiteDawnWindowContext::destroyContext() {
64 if (!fDevice.Get()) {
65 return;
66 }
67
68 this->onDestroyContext();
69
70 fGraphiteRecorder = nullptr;
71 fGraphiteContext = nullptr;
72 fSwapChain = nullptr;
73 fSurface = nullptr;
74 fDevice = nullptr;
75 fInstance = nullptr;
76 }
77
getBackbufferSurface()78 sk_sp<SkSurface> GraphiteDawnWindowContext::getBackbufferSurface() {
79 auto textureView = fSwapChain.GetCurrentTextureView();
80 skgpu::graphite::DawnTextureInfo info(/*sampleCount=*/1,
81 skgpu::Mipmapped::kNo,
82 fSwapChainFormat,
83 kTextureUsage);
84 skgpu::graphite::BackendTexture backendTex(this->dimensions(),
85 info,
86 std::move(textureView));
87 SkASSERT(this->graphiteRecorder());
88 auto surface = SkSurface::MakeGraphiteFromBackendTexture(
89 this->graphiteRecorder(),
90 backendTex,
91 kBGRA_8888_SkColorType,
92 fDisplayParams.fColorSpace,
93 &fDisplayParams.fSurfaceProps);
94 SkASSERT(surface);
95 return surface;
96 }
97
swapBuffers()98 void GraphiteDawnWindowContext::swapBuffers() {
99 // This chunk of code should not be in this class but higher up either in Window or
100 // WindowContext
101 std::unique_ptr<skgpu::graphite::Recording> recording = fGraphiteRecorder->snap();
102 if (recording) {
103 skgpu::graphite::InsertRecordingInfo info;
104 info.fRecording = recording.get();
105 fGraphiteContext->insertRecording(info);
106 fGraphiteContext->submit(skgpu::graphite::SyncToCpu::kNo);
107 }
108
109 fSwapChain.Present();
110 this->onSwapBuffers();
111 }
112
setDisplayParams(const DisplayParams & params)113 void GraphiteDawnWindowContext::setDisplayParams(const DisplayParams& params) {
114 fDisplayParams = params;
115 }
116
createDevice(wgpu::BackendType type)117 wgpu::Device GraphiteDawnWindowContext::createDevice(wgpu::BackendType type) {
118 fInstance->DiscoverDefaultAdapters();
119 DawnProcTable backendProcs = dawn::native::GetProcs();
120 dawnProcSetProcs(&backendProcs);
121
122 std::vector<dawn::native::Adapter> adapters = fInstance->GetAdapters();
123 for (dawn::native::Adapter adapter : adapters) {
124 wgpu::AdapterProperties properties;
125 adapter.GetProperties(&properties);
126 if (properties.backendType != type) {
127 continue;
128 }
129 auto device = wgpu::Device::Acquire(adapter.CreateDevice());
130 device.SetUncapturedErrorCallback(
131 [](WGPUErrorType type, const char* message, void*) {
132 SkDebugf("Device error: %s\n", message);
133 SkASSERT(false);
134 },
135 0);
136 return device;
137 }
138 return nullptr;
139 }
140
createSwapChain()141 wgpu::SwapChain GraphiteDawnWindowContext::createSwapChain() {
142 wgpu::SwapChainDescriptor swapChainDesc;
143 swapChainDesc.usage = kTextureUsage;
144 swapChainDesc.format = fSwapChainFormat;
145 swapChainDesc.width = fWidth;
146 swapChainDesc.height = fHeight;
147 swapChainDesc.presentMode = wgpu::PresentMode::Fifo;
148 swapChainDesc.implementation = 0;
149 auto swapChain = fDevice.CreateSwapChain(fSurface, &swapChainDesc);
150 SkASSERT(swapChain);
151 return swapChain;
152 }
153
154 } //namespace sk_app
155