Skip to content

Commit 986c9d6

Browse files
ArchiverGL: implemented async shader source processing
1 parent 11eeb27 commit 986c9d6

File tree

6 files changed

+113
-40
lines changed

6 files changed

+113
-40
lines changed

Graphics/Archiver/include/SerializationDeviceImpl.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class SerializationDeviceImpl final : public RenderDeviceBase<SerializationEngin
172172
const VkProperties& GetVkProperties() const { return m_VkProps; }
173173
const MtlProperties& GetMtlProperties() const { return m_MtlProps; }
174174

175-
IRenderDevice* GetRenderDevice(RENDER_DEVICE_TYPE Type)
175+
IRenderDevice* GetRenderDevice(RENDER_DEVICE_TYPE Type) const
176176
{
177177
return m_RenderDevices[Type];
178178
}

Graphics/Archiver/include/SerializedShaderImpl.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ class SerializedShaderImpl final : public ObjectBase<ISerializedShader>
7979

8080
virtual IShader* GetDeviceShader() = 0;
8181

82+
virtual SHADER_STATUS GetStatus(bool WaitForCompletion)
83+
{
84+
IShader* pShader = GetDeviceShader();
85+
return pShader != nullptr ? pShader->GetStatus(WaitForCompletion) : SHADER_STATUS_UNINITIALIZED;
86+
}
87+
8288
virtual bool IsCompiling() const = 0;
8389

8490
virtual RefCntAutoPtr<IAsyncTask> GetCompileTask() const = 0;

Graphics/Archiver/src/ArchiverImpl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ Bool ArchiverImpl::SerializeToBlob(Uint32 ContentVersion, IDataBlob** ppBlob)
193193
const auto* Name = shader_it.first.GetStr();
194194
auto& SrcShader = *shader_it.second;
195195
{
196-
const SHADER_STATUS Status = SrcShader.GetStatus(/*WaitForCompletion = */ false);
196+
const SHADER_STATUS Status = SrcShader.GetStatus(/*WaitForCompletion = */ true);
197197
if (Status != SHADER_STATUS_READY)
198198
{
199199
LOG_ERROR_MESSAGE("Shader '", Name, "' is in ", GetShaderStatusString(Status),

Graphics/Archiver/src/Archiver_GL.cpp

Lines changed: 101 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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

287346
private:
@@ -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

429501
struct 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

Graphics/Archiver/src/SerializedShaderImpl.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,10 @@ SHADER_STATUS SerializedShaderImpl::GetStatus(bool WaitForCompletion)
198198
for (size_t type = 0; type < static_cast<size_t>(DeviceType::Count); ++type)
199199
{
200200
const auto& pCompiledShader = m_Shaders[type];
201-
202-
IShader* pShader = pCompiledShader ? pCompiledShader->GetDeviceShader() : nullptr;
203-
if (pShader == nullptr)
201+
if (!pCompiledShader)
204202
continue;
205203

206-
const SHADER_STATUS Status = static_cast<DeviceType>(type) != DeviceType::OpenGL ?
207-
pShader->GetStatus(WaitForCompletion) :
208-
SHADER_STATUS_READY;
204+
const SHADER_STATUS Status = pCompiledShader->GetStatus(WaitForCompletion);
209205
switch (Status)
210206
{
211207
case SHADER_STATUS_UNINITIALIZED:

Tests/DiligentCoreAPITest/src/ArchiveTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ TEST_P(TestBrokenShader, CompileFailure)
421421
RefCntAutoPtr<IShader> pSerializedShader;
422422
RefCntAutoPtr<IDataBlob> pCompilerOutput;
423423
pSerializationDevice->CreateShader(ShaderCI, ShaderArchiveInfo{DataFlag}, &pSerializedShader, pCompilerOutput.RawDblPtr());
424-
if (CompileAsync && DataFlag != ARCHIVE_DEVICE_DATA_FLAG_GL && DataFlag != ARCHIVE_DEVICE_DATA_FLAG_GLES)
424+
if (CompileAsync)
425425
{
426426
ASSERT_NE(pSerializedShader, nullptr);
427427
SHADER_STATUS Status = SHADER_STATUS_UNINITIALIZED;
@@ -477,7 +477,7 @@ TEST_P(TestBrokenShader, MissingSourceFile)
477477

478478
RefCntAutoPtr<IShader> pSerializedShader;
479479
pSerializationDevice->CreateShader(ShaderCI, ShaderArchiveInfo{DataFlag}, pSerializedShader.RawDblPtr());
480-
if (CompileAsync && DataFlag != ARCHIVE_DEVICE_DATA_FLAG_GL && DataFlag != ARCHIVE_DEVICE_DATA_FLAG_GLES)
480+
if (CompileAsync)
481481
{
482482
ASSERT_NE(pSerializedShader, nullptr);
483483
SHADER_STATUS Status = SHADER_STATUS_UNINITIALIZED;

0 commit comments

Comments
 (0)