xref: /aosp_15_r20/external/skia/src/gpu/graphite/dawn/DawnGraphiteUtils.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/dawn/DawnUtils.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnGraphiteUtilsPriv.h"
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ShaderErrorHandler.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/dawn/DawnBackendContext.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextPriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnQueueManager.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnSharedContext.h"
17*c8dee2aaSAndroid Build Coastguard Worker 
18*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker namespace ContextFactory {
MakeDawn(const DawnBackendContext & backendContext,const ContextOptions & options)21*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Context> MakeDawn(const DawnBackendContext& backendContext,
22*c8dee2aaSAndroid Build Coastguard Worker                                   const ContextOptions& options) {
23*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SharedContext> sharedContext = DawnSharedContext::Make(backendContext, options);
24*c8dee2aaSAndroid Build Coastguard Worker     if (!sharedContext) {
25*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
26*c8dee2aaSAndroid Build Coastguard Worker     }
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker     auto queueManager =
29*c8dee2aaSAndroid Build Coastguard Worker             std::make_unique<DawnQueueManager>(backendContext.fQueue, sharedContext.get());
30*c8dee2aaSAndroid Build Coastguard Worker     if (!queueManager) {
31*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
32*c8dee2aaSAndroid Build Coastguard Worker     }
33*c8dee2aaSAndroid Build Coastguard Worker 
34*c8dee2aaSAndroid Build Coastguard Worker     auto context = ContextCtorAccessor::MakeContext(std::move(sharedContext),
35*c8dee2aaSAndroid Build Coastguard Worker                                                     std::move(queueManager),
36*c8dee2aaSAndroid Build Coastguard Worker                                                     options);
37*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(context);
38*c8dee2aaSAndroid Build Coastguard Worker     return context;
39*c8dee2aaSAndroid Build Coastguard Worker }
40*c8dee2aaSAndroid Build Coastguard Worker } // namespace ContextFactory
41*c8dee2aaSAndroid Build Coastguard Worker 
DawnFormatIsDepthOrStencil(wgpu::TextureFormat format)42*c8dee2aaSAndroid Build Coastguard Worker bool DawnFormatIsDepthOrStencil(wgpu::TextureFormat format) {
43*c8dee2aaSAndroid Build Coastguard Worker     switch (format) {
44*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Stencil8:             [[fallthrough]];
45*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth16Unorm:
46*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth32Float:
47*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth24PlusStencil8:
48*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth32FloatStencil8:
49*c8dee2aaSAndroid Build Coastguard Worker             return true;
50*c8dee2aaSAndroid Build Coastguard Worker         default:
51*c8dee2aaSAndroid Build Coastguard Worker             return false;
52*c8dee2aaSAndroid Build Coastguard Worker     }
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker 
DawnFormatIsDepth(wgpu::TextureFormat format)57*c8dee2aaSAndroid Build Coastguard Worker bool DawnFormatIsDepth(wgpu::TextureFormat format) {
58*c8dee2aaSAndroid Build Coastguard Worker     switch (format) {
59*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth16Unorm:         [[fallthrough]];
60*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth32Float:
61*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth24PlusStencil8:
62*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth32FloatStencil8:
63*c8dee2aaSAndroid Build Coastguard Worker             return true;
64*c8dee2aaSAndroid Build Coastguard Worker         default:
65*c8dee2aaSAndroid Build Coastguard Worker             return false;
66*c8dee2aaSAndroid Build Coastguard Worker     }
67*c8dee2aaSAndroid Build Coastguard Worker 
68*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker 
DawnFormatIsStencil(wgpu::TextureFormat format)71*c8dee2aaSAndroid Build Coastguard Worker bool DawnFormatIsStencil(wgpu::TextureFormat format) {
72*c8dee2aaSAndroid Build Coastguard Worker     switch (format) {
73*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Stencil8:             [[fallthrough]];
74*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth24PlusStencil8:
75*c8dee2aaSAndroid Build Coastguard Worker         case wgpu::TextureFormat::Depth32FloatStencil8:
76*c8dee2aaSAndroid Build Coastguard Worker             return true;
77*c8dee2aaSAndroid Build Coastguard Worker         default:
78*c8dee2aaSAndroid Build Coastguard Worker             return false;
79*c8dee2aaSAndroid Build Coastguard Worker     }
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker 
DawnDepthStencilFlagsToFormat(SkEnumBitMask<DepthStencilFlags> mask)84*c8dee2aaSAndroid Build Coastguard Worker wgpu::TextureFormat DawnDepthStencilFlagsToFormat(SkEnumBitMask<DepthStencilFlags> mask) {
85*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Decide if we want to change this to always return a combined depth and stencil format
86*c8dee2aaSAndroid Build Coastguard Worker     // to allow more sharing of depth stencil allocations.
87*c8dee2aaSAndroid Build Coastguard Worker     if (mask == DepthStencilFlags::kDepth) {
88*c8dee2aaSAndroid Build Coastguard Worker         // If needed for workarounds or performance, Depth32Float is also available but requires 2x
89*c8dee2aaSAndroid Build Coastguard Worker         // the amount of memory.
90*c8dee2aaSAndroid Build Coastguard Worker         return wgpu::TextureFormat::Depth16Unorm;
91*c8dee2aaSAndroid Build Coastguard Worker     } else if (mask == DepthStencilFlags::kStencil) {
92*c8dee2aaSAndroid Build Coastguard Worker         return wgpu::TextureFormat::Stencil8;
93*c8dee2aaSAndroid Build Coastguard Worker     } else if (mask == DepthStencilFlags::kDepthStencil) {
94*c8dee2aaSAndroid Build Coastguard Worker         return wgpu::TextureFormat::Depth24PlusStencil8;
95*c8dee2aaSAndroid Build Coastguard Worker     }
96*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(false);
97*c8dee2aaSAndroid Build Coastguard Worker     return wgpu::TextureFormat::Undefined;
98*c8dee2aaSAndroid Build Coastguard Worker }
99*c8dee2aaSAndroid Build Coastguard Worker 
check_shader_module(const DawnSharedContext * sharedContext,wgpu::ShaderModule * module,const char * shaderText,ShaderErrorHandler * errorHandler)100*c8dee2aaSAndroid Build Coastguard Worker static bool check_shader_module([[maybe_unused]] const DawnSharedContext* sharedContext,
101*c8dee2aaSAndroid Build Coastguard Worker                                 wgpu::ShaderModule* module,
102*c8dee2aaSAndroid Build Coastguard Worker                                 const char* shaderText,
103*c8dee2aaSAndroid Build Coastguard Worker                                 ShaderErrorHandler* errorHandler) {
104*c8dee2aaSAndroid Build Coastguard Worker     // Prior to emsdk 3.1.51 wgpu::ShaderModule::GetCompilationInfo is unimplemented.
105*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)                                      &&  \
106*c8dee2aaSAndroid Build Coastguard Worker         ((__EMSCRIPTEN_major__ <  3                               || \
107*c8dee2aaSAndroid Build Coastguard Worker          (__EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ <  1) || \
108*c8dee2aaSAndroid Build Coastguard Worker          (__EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ < 51)))
109*c8dee2aaSAndroid Build Coastguard Worker     return true;
110*c8dee2aaSAndroid Build Coastguard Worker #else
111*c8dee2aaSAndroid Build Coastguard Worker     struct Handler {
112*c8dee2aaSAndroid Build Coastguard Worker         static void Fn(WGPUCompilationInfoRequestStatus status,
113*c8dee2aaSAndroid Build Coastguard Worker                        const WGPUCompilationInfo* info,
114*c8dee2aaSAndroid Build Coastguard Worker                        void* userdata) {
115*c8dee2aaSAndroid Build Coastguard Worker             Handler* self = reinterpret_cast<Handler*>(userdata);
116*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(status == WGPUCompilationInfoRequestStatus_Success);
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker             // Walk the message list and check for hard errors.
119*c8dee2aaSAndroid Build Coastguard Worker             self->fSuccess = true;
120*c8dee2aaSAndroid Build Coastguard Worker             for (size_t index = 0; index < info->messageCount; ++index) {
121*c8dee2aaSAndroid Build Coastguard Worker                 const WGPUCompilationMessage& entry = info->messages[index];
122*c8dee2aaSAndroid Build Coastguard Worker                 if (entry.type == WGPUCompilationMessageType_Error) {
123*c8dee2aaSAndroid Build Coastguard Worker                     self->fSuccess = false;
124*c8dee2aaSAndroid Build Coastguard Worker                     break;
125*c8dee2aaSAndroid Build Coastguard Worker                 }
126*c8dee2aaSAndroid Build Coastguard Worker             }
127*c8dee2aaSAndroid Build Coastguard Worker 
128*c8dee2aaSAndroid Build Coastguard Worker             // If we found a hard error, report the compilation messages to the error handler.
129*c8dee2aaSAndroid Build Coastguard Worker             if (!self->fSuccess) {
130*c8dee2aaSAndroid Build Coastguard Worker                 std::string errors;
131*c8dee2aaSAndroid Build Coastguard Worker                 for (size_t index = 0; index < info->messageCount; ++index) {
132*c8dee2aaSAndroid Build Coastguard Worker                     const WGPUCompilationMessage& entry = info->messages[index];
133*c8dee2aaSAndroid Build Coastguard Worker #if defined(WGPU_BREAKING_CHANGE_STRING_VIEW_OUTPUT_STRUCTS)
134*c8dee2aaSAndroid Build Coastguard Worker                     std::string messageString(entry.message.data, entry.message.length);
135*c8dee2aaSAndroid Build Coastguard Worker #else   // defined(WGPU_BREAKING_CHANGE_STRING_VIEW_OUTPUT_STRUCTS)
136*c8dee2aaSAndroid Build Coastguard Worker                     std::string messageString(entry.message);
137*c8dee2aaSAndroid Build Coastguard Worker #endif  // defined(WGPU_BREAKING_CHANGE_STRING_VIEW_OUTPUT_STRUCTS)
138*c8dee2aaSAndroid Build Coastguard Worker                     errors += "line " + std::to_string(entry.lineNum) + ':' +
139*c8dee2aaSAndroid Build Coastguard Worker                               std::to_string(entry.linePos) + ' ' + messageString + '\n';
140*c8dee2aaSAndroid Build Coastguard Worker                 }
141*c8dee2aaSAndroid Build Coastguard Worker                 self->fErrorHandler->compileError(
142*c8dee2aaSAndroid Build Coastguard Worker                         self->fShaderText, errors.c_str(), /*shaderWasCached=*/false);
143*c8dee2aaSAndroid Build Coastguard Worker             }
144*c8dee2aaSAndroid Build Coastguard Worker         }
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker         const char* fShaderText;
147*c8dee2aaSAndroid Build Coastguard Worker         ShaderErrorHandler* fErrorHandler;
148*c8dee2aaSAndroid Build Coastguard Worker         bool fSuccess = false;
149*c8dee2aaSAndroid Build Coastguard Worker     };
150*c8dee2aaSAndroid Build Coastguard Worker 
151*c8dee2aaSAndroid Build Coastguard Worker     Handler handler;
152*c8dee2aaSAndroid Build Coastguard Worker     handler.fShaderText = shaderText;
153*c8dee2aaSAndroid Build Coastguard Worker     handler.fErrorHandler = errorHandler;
154*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
155*c8dee2aaSAndroid Build Coastguard Worker     // Deprecated function.
156*c8dee2aaSAndroid Build Coastguard Worker     module->GetCompilationInfo(&Handler::Fn, &handler);
157*c8dee2aaSAndroid Build Coastguard Worker #else
158*c8dee2aaSAndroid Build Coastguard Worker     // New API.
159*c8dee2aaSAndroid Build Coastguard Worker     wgpu::FutureWaitInfo waitInfo{};
160*c8dee2aaSAndroid Build Coastguard Worker     waitInfo.future = module->GetCompilationInfo(
161*c8dee2aaSAndroid Build Coastguard Worker             wgpu::CallbackMode::WaitAnyOnly,
162*c8dee2aaSAndroid Build Coastguard Worker             [handlerPtr = &handler](wgpu::CompilationInfoRequestStatus status,
163*c8dee2aaSAndroid Build Coastguard Worker                                     const wgpu::CompilationInfo* info) {
164*c8dee2aaSAndroid Build Coastguard Worker                 Handler::Fn(static_cast<WGPUCompilationInfoRequestStatus>(status),
165*c8dee2aaSAndroid Build Coastguard Worker                             reinterpret_cast<const WGPUCompilationInfo*>(info),
166*c8dee2aaSAndroid Build Coastguard Worker                             handlerPtr);
167*c8dee2aaSAndroid Build Coastguard Worker             });
168*c8dee2aaSAndroid Build Coastguard Worker 
169*c8dee2aaSAndroid Build Coastguard Worker     const auto& instance = static_cast<const DawnSharedContext*>(sharedContext)
170*c8dee2aaSAndroid Build Coastguard Worker                                    ->device()
171*c8dee2aaSAndroid Build Coastguard Worker                                    .GetAdapter()
172*c8dee2aaSAndroid Build Coastguard Worker                                    .GetInstance();
173*c8dee2aaSAndroid Build Coastguard Worker     [[maybe_unused]] auto status =
174*c8dee2aaSAndroid Build Coastguard Worker             instance.WaitAny(1, &waitInfo, /*timeoutNS=*/std::numeric_limits<uint64_t>::max());
175*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(status == wgpu::WaitStatus::Success);
176*c8dee2aaSAndroid Build Coastguard Worker #endif  // defined(__EMSCRIPTEN__)
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker     return handler.fSuccess;
179*c8dee2aaSAndroid Build Coastguard Worker #endif
180*c8dee2aaSAndroid Build Coastguard Worker }
181*c8dee2aaSAndroid Build Coastguard Worker 
DawnCompileWGSLShaderModule(const DawnSharedContext * sharedContext,const char * label,const std::string & wgsl,wgpu::ShaderModule * module,ShaderErrorHandler * errorHandler)182*c8dee2aaSAndroid Build Coastguard Worker bool DawnCompileWGSLShaderModule(const DawnSharedContext* sharedContext,
183*c8dee2aaSAndroid Build Coastguard Worker                                  const char* label,
184*c8dee2aaSAndroid Build Coastguard Worker                                  const std::string& wgsl,
185*c8dee2aaSAndroid Build Coastguard Worker                                  wgpu::ShaderModule* module,
186*c8dee2aaSAndroid Build Coastguard Worker                                  ShaderErrorHandler* errorHandler) {
187*c8dee2aaSAndroid Build Coastguard Worker #ifdef WGPU_BREAKING_CHANGE_DROP_DESCRIPTOR
188*c8dee2aaSAndroid Build Coastguard Worker     wgpu::ShaderSourceWGSL wgslDesc;
189*c8dee2aaSAndroid Build Coastguard Worker #else
190*c8dee2aaSAndroid Build Coastguard Worker     wgpu::ShaderModuleWGSLDescriptor wgslDesc;
191*c8dee2aaSAndroid Build Coastguard Worker #endif
192*c8dee2aaSAndroid Build Coastguard Worker     wgslDesc.code = wgsl.c_str();
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     wgpu::ShaderModuleDescriptor desc;
195*c8dee2aaSAndroid Build Coastguard Worker     desc.nextInChain = &wgslDesc;
196*c8dee2aaSAndroid Build Coastguard Worker     if (sharedContext->caps()->setBackendLabels()) {
197*c8dee2aaSAndroid Build Coastguard Worker         desc.label = label;
198*c8dee2aaSAndroid Build Coastguard Worker     }
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     *module = sharedContext->device().CreateShaderModule(&desc);
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     return check_shader_module(sharedContext, module, wgsl.c_str(), errorHandler);
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
206*c8dee2aaSAndroid Build Coastguard Worker namespace ycbcrUtils {
207*c8dee2aaSAndroid Build Coastguard Worker 
DawnDescriptorIsValid(const wgpu::YCbCrVkDescriptor & desc)208*c8dee2aaSAndroid Build Coastguard Worker bool DawnDescriptorIsValid(const wgpu::YCbCrVkDescriptor& desc) {
209*c8dee2aaSAndroid Build Coastguard Worker     static const wgpu::YCbCrVkDescriptor kDefaultYcbcrDescriptor = {};
210*c8dee2aaSAndroid Build Coastguard Worker     return !DawnDescriptorsAreEquivalent(desc, kDefaultYcbcrDescriptor);
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker 
DawnDescriptorUsesExternalFormat(const wgpu::YCbCrVkDescriptor & desc)213*c8dee2aaSAndroid Build Coastguard Worker bool DawnDescriptorUsesExternalFormat(const wgpu::YCbCrVkDescriptor& desc) {
214*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(desc.externalFormat != 0 || desc.vkFormat != 0);
215*c8dee2aaSAndroid Build Coastguard Worker     return desc.externalFormat != 0;
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker 
218*c8dee2aaSAndroid Build Coastguard Worker } // namespace ycbcrUtils
219*c8dee2aaSAndroid Build Coastguard Worker #endif // !defined(__EMSCRIPTEN__)
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
222