• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "include/gpu/graphite/dawn/DawnUtils.h"
9 #include "src/gpu/graphite/dawn/DawnUtilsPriv.h"
10 
11 #include "include/gpu/ShaderErrorHandler.h"
12 #include "include/gpu/graphite/Context.h"
13 #include "include/gpu/graphite/dawn/DawnBackendContext.h"
14 #include "src/gpu/graphite/ContextPriv.h"
15 #include "src/gpu/graphite/dawn/DawnQueueManager.h"
16 #include "src/gpu/graphite/dawn/DawnSharedContext.h"
17 #include "src/sksl/SkSLCompiler.h"
18 #include "src/sksl/SkSLProgramSettings.h"
19 #include "src/utils/SkShaderUtils.h"
20 
21 namespace skgpu::graphite {
22 
23 namespace ContextFactory {
MakeDawn(const DawnBackendContext & backendContext,const ContextOptions & options)24 std::unique_ptr<Context> MakeDawn(const DawnBackendContext& backendContext,
25                                   const ContextOptions& options) {
26     sk_sp<SharedContext> sharedContext = DawnSharedContext::Make(backendContext, options);
27     if (!sharedContext) {
28         return nullptr;
29     }
30 
31     auto queueManager =
32             std::make_unique<DawnQueueManager>(backendContext.fQueue, sharedContext.get());
33     if (!queueManager) {
34         return nullptr;
35     }
36 
37     auto context = ContextCtorAccessor::MakeContext(std::move(sharedContext),
38                                                     std::move(queueManager),
39                                                     options);
40     SkASSERT(context);
41     return context;
42 }
43 } // namespace ContextFactory
44 
DawnFormatIsDepthOrStencil(wgpu::TextureFormat format)45 bool DawnFormatIsDepthOrStencil(wgpu::TextureFormat format) {
46     switch (format) {
47         case wgpu::TextureFormat::Stencil8: // fallthrough
48         case wgpu::TextureFormat::Depth32Float:
49         case wgpu::TextureFormat::Depth32FloatStencil8:
50             return true;
51         default:
52             return false;
53     }
54 }
55 
DawnFormatIsDepth(wgpu::TextureFormat format)56 bool DawnFormatIsDepth(wgpu::TextureFormat format) {
57     switch (format) {
58         case wgpu::TextureFormat::Depth32Float:
59         case wgpu::TextureFormat::Depth32FloatStencil8:
60             return true;
61         default:
62             return false;
63     }
64 }
65 
DawnFormatIsStencil(wgpu::TextureFormat format)66 bool DawnFormatIsStencil(wgpu::TextureFormat format) {
67     switch (format) {
68         case wgpu::TextureFormat::Stencil8: // fallthrough
69         case wgpu::TextureFormat::Depth32FloatStencil8:
70             return true;
71         default:
72             return false;
73     }
74 }
75 
DawnDepthStencilFlagsToFormat(SkEnumBitMask<DepthStencilFlags> mask)76 wgpu::TextureFormat DawnDepthStencilFlagsToFormat(SkEnumBitMask<DepthStencilFlags> mask) {
77     // TODO: Decide if we want to change this to always return a combined depth and stencil format
78     // to allow more sharing of depth stencil allocations.
79     if (mask == DepthStencilFlags::kDepth) {
80         // wgpu::TextureFormatDepth16Unorm is also a universally supported option here
81         return wgpu::TextureFormat::Depth32Float;
82     } else if (mask == DepthStencilFlags::kStencil) {
83         return wgpu::TextureFormat::Stencil8;
84     } else if (mask == DepthStencilFlags::kDepthStencil) {
85         // wgpu::TextureFormatDepth24Unorm_Stencil8 is supported on Mac family GPUs.
86         return wgpu::TextureFormat::Depth32FloatStencil8;
87     }
88     SkASSERT(false);
89     return wgpu::TextureFormat::Undefined;
90 }
91 
92 // Print the source code for all shaders generated.
93 #ifdef SK_PRINT_SKSL_SHADERS
94 static constexpr bool gPrintSKSL  = true;
95 #else
96 static constexpr bool gPrintSKSL  = false;
97 #endif
SkSLToSPIRV(SkSL::Compiler * compiler,const std::string & sksl,SkSL::ProgramKind programKind,const SkSL::ProgramSettings & settings,std::string * spirv,SkSL::Program::Inputs * outInputs,ShaderErrorHandler * errorHandler)98 bool SkSLToSPIRV(SkSL::Compiler* compiler,
99                  const std::string& sksl,
100                  SkSL::ProgramKind programKind,
101                  const SkSL::ProgramSettings& settings,
102                  std::string* spirv,
103                  SkSL::Program::Inputs* outInputs,
104                  ShaderErrorHandler* errorHandler) {
105 #ifdef SK_DEBUG
106     std::string src = SkShaderUtils::PrettyPrint(sksl);
107 #else
108     const std::string& src = sksl;
109 #endif
110     std::unique_ptr<SkSL::Program> program = compiler->convertProgram(programKind,
111                                                                       src,
112                                                                       settings);
113     if (!program || !compiler->toSPIRV(*program, spirv)) {
114         errorHandler->compileError(src.c_str(), compiler->errorText().c_str());
115         return false;
116     }
117 
118     if (gPrintSKSL) {
119         SkShaderUtils::PrintShaderBanner(programKind);
120         SkDebugf("SKSL:\n");
121         SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(sksl));
122     }
123 
124     *outInputs = program->fInputs;
125     return true;
126 }
127 
DawnCompileSPIRVShaderModule(const DawnSharedContext * sharedContext,const std::string & spirv,ShaderErrorHandler * errorHandler)128 wgpu::ShaderModule DawnCompileSPIRVShaderModule(const DawnSharedContext* sharedContext,
129                                                 const std::string& spirv,
130                                                 ShaderErrorHandler* errorHandler) {
131     wgpu::ShaderModuleSPIRVDescriptor spirvDesc;
132     spirvDesc.codeSize = spirv.size() / 4;
133     spirvDesc.code = reinterpret_cast<const uint32_t*>(spirv.c_str());
134 
135     // Skia often generates shaders that select a texture/sampler conditionally based on an
136     // attribute (specifically in the case of texture atlas indexing). We disable derivative
137     // uniformity warnings as we expect Skia's behavior to result in well-defined values.
138     wgpu::DawnShaderModuleSPIRVOptionsDescriptor dawnSpirvOptions;
139     dawnSpirvOptions.allowNonUniformDerivatives = true;
140 
141     wgpu::ShaderModuleDescriptor desc;
142     desc.nextInChain = &spirvDesc;
143     spirvDesc.nextInChain = &dawnSpirvOptions;
144 
145     return sharedContext->device().CreateShaderModule(&desc);
146 }
147 
148 } // namespace skgpu::graphite
149