@@ -206,56 +206,90 @@ static void AppendGLES30Stubs(std::string& Source)
206206
207207#endif
208208
209- struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
209+ class CompiledShaderGL final : public SerializedShaderImpl::CompiledShader
210210{
211- String UnrolledSource;
212- RefCntAutoPtr<IShader> pShaderGL;
213- bool IsOptimized = false ;
214-
215- CompiledShaderGL (IReferenceCounters* pRefCounters ,
216- const ShaderCreateInfo& ShaderCI,
217- const ShaderGLImpl::CreateInfo& GLShaderCI ,
218- IRenderDevice* pRenderDeviceGL ,
219- RENDER_DEVICE_TYPE DeviceType ,
220- const SerializationDeviceImpl::GLProperties& GLProps)
211+ public:
212+ CompiledShaderGL (IReferenceCounters* pRefCounters,
213+ const ShaderCreateInfo& ShaderCI,
214+ const ShaderGLImpl::CreateInfo& GLShaderCI,
215+ const SerializationDeviceImpl* pSerializationDevice ,
216+ RENDER_DEVICE_TYPE DeviceType) :
217+ m_pSerializationDevice{pSerializationDevice} ,
218+ m_ShaderCI{ShaderCI, GetRawAllocator ()} ,
219+ m_GLShaderCI{GLShaderCI} ,
220+ m_DeviceType{DeviceType}
221221 {
222+ IThreadPool* pCompilationThreadPool = pSerializationDevice->GetShaderCompilationThreadPool ();
223+
224+ m_Status.store (SHADER_STATUS_COMPILING);
225+ if (pCompilationThreadPool == nullptr || (ShaderCI.CompileFlags & SHADER_COMPILE_FLAG_ASYNCHRONOUS) == 0 )
226+ {
227+ InitializeSource ();
228+ CreateGLShader ();
229+ }
230+ else
231+ {
232+ this ->m_AsyncInitializer = AsyncInitializer::Start (
233+ pCompilationThreadPool,
234+ [this ](Uint32 ThreadId) //
235+ {
236+ try
237+ {
238+ InitializeSource ();
239+ }
240+ catch (...)
241+ {
242+ m_Status.store (SHADER_STATUS_FAILED);
243+ }
244+ });
245+ }
246+ }
247+
248+ void InitializeSource ()
249+ {
250+ const SerializationDeviceImpl::GLProperties& GLProps = m_pSerializationDevice->GetGLProperties ();
222251 if (GLProps.OptimizeShaders )
223252 {
224- UnrolledSource = TransformSource (ShaderCI, GLShaderCI, DeviceType , GLProps);
225- IsOptimized = !UnrolledSource .empty ();
253+ m_UnrolledSource = TransformSource (m_ShaderCI, m_GLShaderCI, m_DeviceType , GLProps);
254+ m_IsOptimized = !m_UnrolledSource .empty ();
226255 }
227- if (UnrolledSource .empty ())
256+ if (m_UnrolledSource .empty ())
228257 {
229- UnrolledSource = UnrollSource (ShaderCI );
258+ m_UnrolledSource = UnrollSource (m_ShaderCI );
230259 }
231- VERIFY_EXPR (!UnrolledSource.empty ());
260+ VERIFY_EXPR (!m_UnrolledSource.empty ());
261+
262+ m_Status.store (SHADER_STATUS_READY);
263+ }
232264
265+ void CreateGLShader ()
266+ {
233267 // Use serialization CI to be consistent with what will be saved in the archive.
234- const auto SerializationCI = GetSerializationCI (ShaderCI );
235- if (pRenderDeviceGL)
268+ const ShaderCreateInfo SerializationCI = GetSerializationCI (m_ShaderCI );
269+ if (IRenderDevice* pRenderDeviceGL = m_pSerializationDevice-> GetRenderDevice (m_DeviceType) )
236270 {
237271 // GL shader must be created through the render device as GL functions
238272 // are not loaded by the archiver.
239- pRenderDeviceGL->CreateShader (SerializationCI, &pShaderGL );
240- if (!pShaderGL )
241- LOG_ERROR_AND_THROW (" Failed to create GL shader '" , (ShaderCI. Desc .Name ? ShaderCI .Desc .Name : " " ), " '." );
273+ pRenderDeviceGL->CreateShader (SerializationCI, &m_pShaderGL );
274+ if (!m_pShaderGL )
275+ LOG_ERROR_AND_THROW (" Failed to create GL shader '" , (m_ShaderCI. Get (). Desc .Name ? m_ShaderCI. Get () .Desc .Name : " " ), " '." );
242276 }
243277 else
244278 {
245- pShaderGL = NEW_RC_OBJ (GetRawAllocator (), " Shader instance" , ShaderGLImpl)(nullptr , SerializationCI, GLShaderCI , true /* bIsDeviceInternal*/ );
279+ m_pShaderGL = NEW_RC_OBJ (GetRawAllocator (), " Shader instance" , ShaderGLImpl)(nullptr , SerializationCI, m_GLShaderCI , true /* bIsDeviceInternal*/ );
246280 }
247281 }
248282
249283 ShaderCreateInfo GetSerializationCI (ShaderCreateInfo ShaderCI) const
250284 {
251285 ShaderCI.FilePath = nullptr ;
252286 ShaderCI.ByteCode = nullptr ;
253- ShaderCI.Source = UnrolledSource .c_str ();
254- ShaderCI.SourceLength = UnrolledSource .length ();
287+ ShaderCI.Source = m_UnrolledSource .c_str ();
288+ ShaderCI.SourceLength = m_UnrolledSource .length ();
255289 ShaderCI.ShaderCompiler = SHADER_COMPILER_DEFAULT;
256290 ShaderCI.Macros = {}; // Macros are inlined into unrolled source
257291
258- if (IsOptimized )
292+ if (m_IsOptimized )
259293 {
260294 ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL;
261295 ShaderCI.EntryPoint = " main" ;
@@ -271,17 +305,42 @@ struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
271305
272306 virtual IShader* GetDeviceShader () override final
273307 {
274- return pShaderGL;
308+ if (m_pShaderGL == nullptr )
309+ {
310+ if (m_Status.load () == SHADER_STATUS_READY)
311+ {
312+ try
313+ {
314+ CreateGLShader ();
315+ }
316+ catch (...)
317+ {
318+ m_Status.store (SHADER_STATUS_FAILED);
319+ }
320+ }
321+ }
322+ return m_pShaderGL;
275323 }
276324
277325 virtual bool IsCompiling () const override final
278326 {
279- return false ;
327+ return m_Status.load () <= SHADER_STATUS_COMPILING;
328+ }
329+
330+ virtual SHADER_STATUS GetStatus (bool WaitForCompletion) override final
331+ {
332+ VERIFY_EXPR (m_Status.load () != SHADER_STATUS_UNINITIALIZED);
333+ ASYNC_TASK_STATUS InitTaskStatus = AsyncInitializer::Update (m_AsyncInitializer, WaitForCompletion);
334+ if (InitTaskStatus == ASYNC_TASK_STATUS_COMPLETE)
335+ {
336+ VERIFY (m_Status.load () > SHADER_STATUS_COMPILING, " Shader status must be atomically set by the compiling task before it finishes" );
337+ }
338+ return m_Status.load ();
280339 }
281340
282341 virtual RefCntAutoPtr<IAsyncTask> GetCompileTask () const override final
283342 {
284- return {} ;
343+ return AsyncInitializer::GetAsyncTask (m_AsyncInitializer) ;
285344 }
286345
287346private:
@@ -424,6 +483,19 @@ struct CompiledShaderGL final : SerializedShaderImpl::CompiledShader
424483
425484 return OptimizedGLSL;
426485 }
486+
487+ private:
488+ const SerializationDeviceImpl* const m_pSerializationDevice;
489+ const ShaderCreateInfoWrapper m_ShaderCI;
490+ const ShaderGLImpl::CreateInfo m_GLShaderCI;
491+ const RENDER_DEVICE_TYPE m_DeviceType;
492+
493+ std::unique_ptr<AsyncInitializer> m_AsyncInitializer;
494+ std::atomic<SHADER_STATUS> m_Status{SHADER_STATUS_UNINITIALIZED};
495+
496+ String m_UnrolledSource;
497+ RefCntAutoPtr<IShader> m_pShaderGL;
498+ bool m_IsOptimized = false ;
427499};
428500
429501struct ShaderStageInfoGL
@@ -541,8 +613,7 @@ void SerializedShaderImpl::CreateShaderGL(IReferenceCounters* pRefCounters,
541613 ppCompilerOutput == nullptr || *ppCompilerOutput == nullptr ? ppCompilerOutput : nullptr ,
542614 };
543615
544- CreateShader<CompiledShaderGL>(DeviceType::OpenGL, pRefCounters, ShaderCI, GLShaderCI, m_pDevice->GetRenderDevice (DeviceType),
545- DeviceType, m_pDevice->GetGLProperties ());
616+ CreateShader<CompiledShaderGL>(DeviceType::OpenGL, pRefCounters, ShaderCI, GLShaderCI, m_pDevice, DeviceType);
546617}
547618
548619} // namespace Diligent
0 commit comments