@@ -458,6 +458,7 @@ namespace Babylon
458458                InstanceMethod (" updateDynamicVertexBuffer" 
459459
460460                InstanceMethod (" createProgram" 
461+                 InstanceMethod (" createProgramAsync" 
461462                InstanceMethod (" getUniforms" 
462463                InstanceMethod (" getAttributes" 
463464
@@ -687,22 +688,11 @@ namespace Babylon
687688        return  vertexSource;
688689    }
689690
690-     Napi::Value  NativeEngine::CreateProgram  (const  Napi::CallbackInfo& info )
691+     std::unique_ptr<ProgramData>  NativeEngine::CreateProgramInternal  (const  std::string vertexSource,  const  std::string fragmentSource )
691692    {
692-         const  std::string vertexSource = info[0 ].As <Napi::String>().Utf8Value ();
693-         const  std::string fragmentSource = info[1 ].As <Napi::String>().Utf8Value ();
693+         ShaderCompiler::BgfxShaderInfo shaderInfo = m_shaderCompiler.Compile (ProcessShaderCoordinates (vertexSource), ProcessSamplerFlip (fragmentSource));
694694
695-         ProgramData* program = new  ProgramData{};
696-         ShaderCompiler::BgfxShaderInfo shaderInfo{};
697- 
698-         try 
699-         {
700-             shaderInfo = m_shaderCompiler.Compile (ProcessShaderCoordinates (vertexSource), ProcessSamplerFlip (fragmentSource));
701-         }
702-         catch  (const  std::exception& ex)
703-         {
704-             throw  Napi::Error::New (info.Env (), ex.what ());
705-         }
695+         std::unique_ptr<ProgramData> program = std::make_unique<ProgramData>();
706696
707697        static  auto  InitUniformInfos{
708698            [](bgfx::ShaderHandle shader, const  std::unordered_map<std::string, uint8_t >& uniformStages, std::unordered_map<uint16_t , UniformInfo>& uniformInfos, std::unordered_map<std::string, uint16_t >& uniformNameToIndex) {
@@ -724,13 +714,67 @@ namespace Babylon
724714
725715        auto  vertexShader = bgfx::createShader (bgfx::copy (shaderInfo.VertexBytes .data (), static_cast <uint32_t >(shaderInfo.VertexBytes .size ())));
726716        InitUniformInfos (vertexShader, shaderInfo.UniformStages , program->UniformInfos , program->UniformNameToIndex );
727-         program->VertexAttributeLocations  = std::move (shaderInfo.VertexAttributeLocations );
728717
729718        auto  fragmentShader = bgfx::createShader (bgfx::copy (shaderInfo.FragmentBytes .data (), static_cast <uint32_t >(shaderInfo.FragmentBytes .size ())));
730719        InitUniformInfos (fragmentShader, shaderInfo.UniformStages , program->UniformInfos , program->UniformNameToIndex );
731720
732721        program->Handle  = bgfx::createProgram (vertexShader, fragmentShader, true );
733-         return  Napi::Pointer<ProgramData>::Create (info.Env (), program, Napi::NapiPointerDeleter (program));
722+         program->VertexAttributeLocations  = std::move (shaderInfo.VertexAttributeLocations );
723+ 
724+         return  program;
725+     }
726+ 
727+     Napi::Value NativeEngine::CreateProgram (const  Napi::CallbackInfo& info)
728+     {
729+         const  std::string vertexSource = info[0 ].As <Napi::String>().Utf8Value ();
730+         const  std::string fragmentSource = info[1 ].As <Napi::String>().Utf8Value ();
731+         ProgramData* program = new  ProgramData{};
732+         Napi::Value jsProgram = Napi::Pointer<ProgramData>::Create (info.Env (), program, Napi::NapiPointerDeleter (program));
733+         try 
734+         {
735+             *program = std::move (*CreateProgramInternal (vertexSource, fragmentSource));
736+         }
737+         catch  (const  std::exception& ex)
738+         {
739+             throw  Napi::Error::New (info.Env (), ex.what ());
740+         }
741+         return  jsProgram;
742+     }
743+ 
744+     Napi::Value NativeEngine::CreateProgramAsync (const  Napi::CallbackInfo& info)
745+     {
746+         const  std::string vertexSource = info[0 ].As <Napi::String>().Utf8Value ();
747+         const  std::string fragmentSource = info[1 ].As <Napi::String>().Utf8Value ();
748+         const  Napi::Function onSuccess = info[2 ].As <Napi::Function>();
749+         const  Napi::Function onError = info[3 ].As <Napi::Function>();
750+ 
751+         ProgramData* program = new  ProgramData{};
752+         Napi::Value jsProgram = Napi::Pointer<ProgramData>::Create (info.Env (), program, Napi::NapiPointerDeleter (program));
753+ 
754+         arcana::make_task (arcana::threadpool_scheduler, *m_cancellationSource,
755+             [this , vertexSource, fragmentSource, cancellationSource{m_cancellationSource}]() -> std::unique_ptr<ProgramData>
756+             {
757+                 return  CreateProgramInternal (vertexSource, fragmentSource);
758+             })
759+             .then (m_runtimeScheduler, *m_cancellationSource,
760+                 [program,
761+                     jsProgramRef{Napi::Persistent (jsProgram)},
762+                     onSuccessRef{Napi::Persistent (onSuccess)},
763+                     onErrorRef{Napi::Persistent (onError)},
764+                     cancellationSource{m_cancellationSource}](const  arcana::expected<std::unique_ptr<ProgramData>, std::exception_ptr>& result)
765+                 {
766+                     if  (result.has_error ())
767+                     {
768+                         onErrorRef.Call ({Napi::Error::New (onErrorRef.Env (), result.error ()).Value ()});
769+                     }
770+                     else 
771+                     {
772+                         *program = std::move (*result.value ());
773+                         onSuccessRef.Call ({});
774+                     }
775+                 });
776+ 
777+         return  jsProgram;
734778    }
735779
736780    Napi::Value NativeEngine::GetUniforms (const  Napi::CallbackInfo& info)
0 commit comments