• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ProgramWgpu.cpp:
7 //    Implements the class methods for ProgramWgpu.
8 //
9 
10 #include "libANGLE/renderer/wgpu/ProgramWgpu.h"
11 
12 #include "common/debug.h"
13 #include "libANGLE/renderer/wgpu/ProgramExecutableWgpu.h"
14 #include "libANGLE/renderer/wgpu/wgpu_utils.h"
15 #include "libANGLE/trace.h"
16 
17 #include <dawn/webgpu_cpp.h>
18 
19 namespace rx
20 {
21 namespace
22 {
23 class CreateWGPUShaderModuleTask : public LinkSubTask
24 {
25   public:
CreateWGPUShaderModuleTask(wgpu::Instance instance,wgpu::Device device,const gl::SharedCompiledShaderState & compiledShaderState,TranslatedWGPUShaderModule & resultShaderModule)26     CreateWGPUShaderModuleTask(wgpu::Instance instance,
27                                wgpu::Device device,
28                                const gl::SharedCompiledShaderState &compiledShaderState,
29                                TranslatedWGPUShaderModule &resultShaderModule)
30         : mInstance(instance),
31           mDevice(device),
32           mCompiledShaderState(compiledShaderState),
33           mShaderModule(resultShaderModule)
34     {}
35 
getResult(const gl::Context * context,gl::InfoLog & infoLog)36     angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
37     {
38         infoLog << mLog.str();
39         return mResult;
40     }
41 
operator ()()42     void operator()() override
43     {
44         ANGLE_TRACE_EVENT0("gpu.angle", "CreateWGPUShaderModuleTask");
45 
46         wgpu::ShaderModuleWGSLDescriptor shaderModuleWGSLDescriptor;
47         shaderModuleWGSLDescriptor.code = mCompiledShaderState->translatedSource.c_str();
48 
49         wgpu::ShaderModuleDescriptor shaderModuleDescriptor;
50         shaderModuleDescriptor.nextInChain = &shaderModuleWGSLDescriptor;
51 
52         mShaderModule.module = mDevice.CreateShaderModule(&shaderModuleDescriptor);
53 
54         wgpu::CompilationInfoCallbackInfo callbackInfo;
55         callbackInfo.mode     = wgpu::CallbackMode::WaitAnyOnly;
56         callbackInfo.callback = [](WGPUCompilationInfoRequestStatus status,
57                                    struct WGPUCompilationInfo const *compilationInfo,
58                                    void *userdata) {
59             CreateWGPUShaderModuleTask *task = static_cast<CreateWGPUShaderModuleTask *>(userdata);
60 
61             if (status != WGPUCompilationInfoRequestStatus_Success)
62             {
63                 task->mResult = angle::Result::Stop;
64             }
65 
66             for (size_t msgIdx = 0; msgIdx < compilationInfo->messageCount; ++msgIdx)
67             {
68                 const WGPUCompilationMessage &message = compilationInfo->messages[msgIdx];
69                 switch (message.type)
70                 {
71                     case WGPUCompilationMessageType_Error:
72                         task->mLog << "Error: ";
73                         break;
74                     case WGPUCompilationMessageType_Warning:
75                         task->mLog << "Warning: ";
76                         break;
77                     case WGPUCompilationMessageType_Info:
78                         task->mLog << "Info: ";
79                         break;
80                     default:
81                         task->mLog << "Unknown: ";
82                         break;
83                 }
84                 task->mLog << message.lineNum << ":" << message.linePos << ": " << message.message
85                            << std::endl;
86             }
87         };
88         callbackInfo.userdata = this;
89 
90         wgpu::FutureWaitInfo waitInfo;
91         waitInfo.future = mShaderModule.module.GetCompilationInfo(callbackInfo);
92 
93         wgpu::WaitStatus waitStatus = mInstance.WaitAny(1, &waitInfo, -1);
94         if (waitStatus != wgpu::WaitStatus::Success)
95         {
96             mResult = angle::Result::Stop;
97         }
98     }
99 
100   private:
101     wgpu::Instance mInstance;
102     wgpu::Device mDevice;
103     gl::SharedCompiledShaderState mCompiledShaderState;
104 
105     TranslatedWGPUShaderModule &mShaderModule;
106 
107     std::ostringstream mLog;
108     angle::Result mResult = angle::Result::Continue;
109 };
110 
111 class LinkTaskWgpu : public LinkTask
112 {
113   public:
LinkTaskWgpu(wgpu::Instance instance,wgpu::Device device,ProgramWgpu * program)114     LinkTaskWgpu(wgpu::Instance instance, wgpu::Device device, ProgramWgpu *program)
115         : mInstance(instance), mDevice(device), mProgram(program)
116     {}
117     ~LinkTaskWgpu() override = default;
118 
link(const gl::ProgramLinkedResources & resources,const gl::ProgramMergedVaryings & mergedVaryings,std::vector<std::shared_ptr<LinkSubTask>> * linkSubTasksOut,std::vector<std::shared_ptr<LinkSubTask>> * postLinkSubTasksOut)119     void link(const gl::ProgramLinkedResources &resources,
120               const gl::ProgramMergedVaryings &mergedVaryings,
121               std::vector<std::shared_ptr<LinkSubTask>> *linkSubTasksOut,
122               std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut) override
123     {
124         ASSERT(linkSubTasksOut && linkSubTasksOut->empty());
125         ASSERT(postLinkSubTasksOut && postLinkSubTasksOut->empty());
126 
127         ProgramExecutableWgpu *executable =
128             GetImplAs<ProgramExecutableWgpu>(&mProgram->getState().getExecutable());
129 
130         const gl::ShaderMap<gl::SharedCompiledShaderState> &shaders =
131             mProgram->getState().getAttachedShaders();
132         for (gl::ShaderType shaderType : gl::AllShaderTypes())
133         {
134             if (shaders[shaderType])
135             {
136                 auto task = std::make_shared<CreateWGPUShaderModuleTask>(
137                     mInstance, mDevice, shaders[shaderType],
138                     executable->getShaderModule(shaderType));
139                 linkSubTasksOut->push_back(task);
140             }
141         }
142     }
143 
getResult(const gl::Context * context,gl::InfoLog & infoLog)144     angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
145     {
146         return angle::Result::Continue;
147     }
148 
149   private:
150     wgpu::Instance mInstance;
151     wgpu::Device mDevice;
152     ProgramWgpu *mProgram = nullptr;
153 };
154 }  // anonymous namespace
155 
ProgramWgpu(const gl::ProgramState & state)156 ProgramWgpu::ProgramWgpu(const gl::ProgramState &state) : ProgramImpl(state) {}
157 
~ProgramWgpu()158 ProgramWgpu::~ProgramWgpu() {}
159 
load(const gl::Context * context,gl::BinaryInputStream * stream,std::shared_ptr<LinkTask> * loadTaskOut,egl::CacheGetResult * resultOut)160 angle::Result ProgramWgpu::load(const gl::Context *context,
161                                 gl::BinaryInputStream *stream,
162                                 std::shared_ptr<LinkTask> *loadTaskOut,
163                                 egl::CacheGetResult *resultOut)
164 {
165     *loadTaskOut = {};
166     *resultOut   = egl::CacheGetResult::Success;
167     return angle::Result::Continue;
168 }
169 
save(const gl::Context * context,gl::BinaryOutputStream * stream)170 void ProgramWgpu::save(const gl::Context *context, gl::BinaryOutputStream *stream) {}
171 
setBinaryRetrievableHint(bool retrievable)172 void ProgramWgpu::setBinaryRetrievableHint(bool retrievable) {}
173 
setSeparable(bool separable)174 void ProgramWgpu::setSeparable(bool separable) {}
175 
link(const gl::Context * context,std::shared_ptr<LinkTask> * linkTaskOut)176 angle::Result ProgramWgpu::link(const gl::Context *context, std::shared_ptr<LinkTask> *linkTaskOut)
177 {
178     wgpu::Device device     = webgpu::GetDevice(context);
179     wgpu::Instance instance = webgpu::GetInstance(context);
180 
181     *linkTaskOut = std::shared_ptr<LinkTask>(new LinkTaskWgpu(instance, device, this));
182     return angle::Result::Continue;
183 }
184 
validate(const gl::Caps & caps)185 GLboolean ProgramWgpu::validate(const gl::Caps &caps)
186 {
187     return GL_TRUE;
188 }
189 
190 }  // namespace rx
191