1 // Copyright 2020 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "dawn_native/CreatePipelineAsyncTask.h" 16 17 #include "dawn_native/AsyncTask.h" 18 #include "dawn_native/ComputePipeline.h" 19 #include "dawn_native/Device.h" 20 #include "dawn_native/RenderPipeline.h" 21 #include "dawn_platform/DawnPlatform.h" 22 #include "dawn_platform/tracing/TraceEvent.h" 23 #include "utils/WGPUHelpers.h" 24 25 namespace dawn_native { 26 CreatePipelineAsyncCallbackTaskBase(std::string errorMessage,void * userdata)27 CreatePipelineAsyncCallbackTaskBase::CreatePipelineAsyncCallbackTaskBase( 28 std::string errorMessage, 29 void* userdata) 30 : mErrorMessage(errorMessage), mUserData(userdata) { 31 } 32 CreateComputePipelineAsyncCallbackTask(Ref<ComputePipelineBase> pipeline,std::string errorMessage,WGPUCreateComputePipelineAsyncCallback callback,void * userdata)33 CreateComputePipelineAsyncCallbackTask::CreateComputePipelineAsyncCallbackTask( 34 Ref<ComputePipelineBase> pipeline, 35 std::string errorMessage, 36 WGPUCreateComputePipelineAsyncCallback callback, 37 void* userdata) 38 : CreatePipelineAsyncCallbackTaskBase(errorMessage, userdata), 39 mPipeline(std::move(pipeline)), 40 mCreateComputePipelineAsyncCallback(callback) { 41 } 42 Finish()43 void CreateComputePipelineAsyncCallbackTask::Finish() { 44 ASSERT(mCreateComputePipelineAsyncCallback != nullptr); 45 46 if (mPipeline.Get() != nullptr) { 47 mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Success, 48 ToAPI(mPipeline.Detach()), "", mUserData); 49 } else { 50 mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Error, nullptr, 51 mErrorMessage.c_str(), mUserData); 52 } 53 } 54 HandleShutDown()55 void CreateComputePipelineAsyncCallbackTask::HandleShutDown() { 56 ASSERT(mCreateComputePipelineAsyncCallback != nullptr); 57 58 mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceDestroyed, nullptr, 59 "Device destroyed before callback", mUserData); 60 } 61 HandleDeviceLoss()62 void CreateComputePipelineAsyncCallbackTask::HandleDeviceLoss() { 63 ASSERT(mCreateComputePipelineAsyncCallback != nullptr); 64 65 mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceLost, nullptr, 66 "Device lost before callback", mUserData); 67 } 68 CreateRenderPipelineAsyncCallbackTask(Ref<RenderPipelineBase> pipeline,std::string errorMessage,WGPUCreateRenderPipelineAsyncCallback callback,void * userdata)69 CreateRenderPipelineAsyncCallbackTask::CreateRenderPipelineAsyncCallbackTask( 70 Ref<RenderPipelineBase> pipeline, 71 std::string errorMessage, 72 WGPUCreateRenderPipelineAsyncCallback callback, 73 void* userdata) 74 : CreatePipelineAsyncCallbackTaskBase(errorMessage, userdata), 75 mPipeline(std::move(pipeline)), 76 mCreateRenderPipelineAsyncCallback(callback) { 77 } 78 Finish()79 void CreateRenderPipelineAsyncCallbackTask::Finish() { 80 ASSERT(mCreateRenderPipelineAsyncCallback != nullptr); 81 82 if (mPipeline.Get() != nullptr) { 83 mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Success, 84 ToAPI(mPipeline.Detach()), "", mUserData); 85 } else { 86 mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Error, nullptr, 87 mErrorMessage.c_str(), mUserData); 88 } 89 } 90 HandleShutDown()91 void CreateRenderPipelineAsyncCallbackTask::HandleShutDown() { 92 ASSERT(mCreateRenderPipelineAsyncCallback != nullptr); 93 94 mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceDestroyed, nullptr, 95 "Device destroyed before callback", mUserData); 96 } 97 HandleDeviceLoss()98 void CreateRenderPipelineAsyncCallbackTask::HandleDeviceLoss() { 99 ASSERT(mCreateRenderPipelineAsyncCallback != nullptr); 100 101 mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_DeviceLost, nullptr, 102 "Device lost before callback", mUserData); 103 } 104 CreateComputePipelineAsyncTask(Ref<ComputePipelineBase> nonInitializedComputePipeline,WGPUCreateComputePipelineAsyncCallback callback,void * userdata)105 CreateComputePipelineAsyncTask::CreateComputePipelineAsyncTask( 106 Ref<ComputePipelineBase> nonInitializedComputePipeline, 107 WGPUCreateComputePipelineAsyncCallback callback, 108 void* userdata) 109 : mComputePipeline(std::move(nonInitializedComputePipeline)), 110 mCallback(callback), 111 mUserdata(userdata) { 112 ASSERT(mComputePipeline != nullptr); 113 } 114 Run()115 void CreateComputePipelineAsyncTask::Run() { 116 const char* eventLabel = utils::GetLabelForTrace(mComputePipeline->GetLabel().c_str()); 117 TRACE_EVENT_FLOW_END1(mComputePipeline->GetDevice()->GetPlatform(), General, 118 "CreateComputePipelineAsyncTask::RunAsync", this, "label", 119 eventLabel); 120 TRACE_EVENT1(mComputePipeline->GetDevice()->GetPlatform(), General, 121 "CreateComputePipelineAsyncTask::Run", "label", eventLabel); 122 123 MaybeError maybeError = mComputePipeline->Initialize(); 124 std::string errorMessage; 125 if (maybeError.IsError()) { 126 mComputePipeline = nullptr; 127 errorMessage = maybeError.AcquireError()->GetMessage(); 128 } 129 130 mComputePipeline->GetDevice()->AddComputePipelineAsyncCallbackTask( 131 mComputePipeline, errorMessage, mCallback, mUserdata); 132 } 133 RunAsync(std::unique_ptr<CreateComputePipelineAsyncTask> task)134 void CreateComputePipelineAsyncTask::RunAsync( 135 std::unique_ptr<CreateComputePipelineAsyncTask> task) { 136 DeviceBase* device = task->mComputePipeline->GetDevice(); 137 138 const char* eventLabel = 139 utils::GetLabelForTrace(task->mComputePipeline->GetLabel().c_str()); 140 141 // Using "taskPtr = std::move(task)" causes compilation error while it should be supported 142 // since C++14: 143 // https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-160 144 auto asyncTask = [taskPtr = task.release()] { 145 std::unique_ptr<CreateComputePipelineAsyncTask> innnerTaskPtr(taskPtr); 146 innnerTaskPtr->Run(); 147 }; 148 149 TRACE_EVENT_FLOW_BEGIN1(device->GetPlatform(), General, 150 "CreateComputePipelineAsyncTask::RunAsync", task.get(), "label", 151 eventLabel); 152 device->GetAsyncTaskManager()->PostTask(std::move(asyncTask)); 153 } 154 CreateRenderPipelineAsyncTask(Ref<RenderPipelineBase> nonInitializedRenderPipeline,WGPUCreateRenderPipelineAsyncCallback callback,void * userdata)155 CreateRenderPipelineAsyncTask::CreateRenderPipelineAsyncTask( 156 Ref<RenderPipelineBase> nonInitializedRenderPipeline, 157 WGPUCreateRenderPipelineAsyncCallback callback, 158 void* userdata) 159 : mRenderPipeline(std::move(nonInitializedRenderPipeline)), 160 mCallback(callback), 161 mUserdata(userdata) { 162 ASSERT(mRenderPipeline != nullptr); 163 } 164 Run()165 void CreateRenderPipelineAsyncTask::Run() { 166 const char* eventLabel = utils::GetLabelForTrace(mRenderPipeline->GetLabel().c_str()); 167 TRACE_EVENT_FLOW_END1(mRenderPipeline->GetDevice()->GetPlatform(), General, 168 "CreateRenderPipelineAsyncTask::RunAsync", this, "label", eventLabel); 169 TRACE_EVENT1(mRenderPipeline->GetDevice()->GetPlatform(), General, 170 "CreateRenderPipelineAsyncTask::Run", "label", eventLabel); 171 172 MaybeError maybeError = mRenderPipeline->Initialize(); 173 std::string errorMessage; 174 if (maybeError.IsError()) { 175 mRenderPipeline = nullptr; 176 errorMessage = maybeError.AcquireError()->GetMessage(); 177 } 178 179 mRenderPipeline->GetDevice()->AddRenderPipelineAsyncCallbackTask( 180 mRenderPipeline, errorMessage, mCallback, mUserdata); 181 } 182 RunAsync(std::unique_ptr<CreateRenderPipelineAsyncTask> task)183 void CreateRenderPipelineAsyncTask::RunAsync( 184 std::unique_ptr<CreateRenderPipelineAsyncTask> task) { 185 DeviceBase* device = task->mRenderPipeline->GetDevice(); 186 187 const char* eventLabel = utils::GetLabelForTrace(task->mRenderPipeline->GetLabel().c_str()); 188 189 // Using "taskPtr = std::move(task)" causes compilation error while it should be supported 190 // since C++14: 191 // https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-160 192 auto asyncTask = [taskPtr = task.release()] { 193 std::unique_ptr<CreateRenderPipelineAsyncTask> innerTaskPtr(taskPtr); 194 innerTaskPtr->Run(); 195 }; 196 197 TRACE_EVENT_FLOW_BEGIN1(device->GetPlatform(), General, 198 "CreateRenderPipelineAsyncTask::RunAsync", task.get(), "label", 199 eventLabel); 200 device->GetAsyncTaskManager()->PostTask(std::move(asyncTask)); 201 } 202 } // namespace dawn_native 203