@@ -458,6 +458,7 @@ namespace Babylon
458458 InstanceMethod (" updateDynamicVertexBuffer" , &NativeEngine::UpdateDynamicVertexBuffer),
459459
460460 InstanceMethod (" createProgram" , &NativeEngine::CreateProgram),
461+ InstanceMethod (" createProgramAsync" , &NativeEngine::CreateProgramAsync),
461462 InstanceMethod (" getUniforms" , &NativeEngine::GetUniforms),
462463 InstanceMethod (" getAttributes" , &NativeEngine::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