Skip to content

Commit 4b3ad5d

Browse files
Render state cache: enabled asynchronous shaders
1 parent 74020b4 commit 4b3ad5d

File tree

2 files changed

+82
-36
lines changed

2 files changed

+82
-36
lines changed

Graphics/GraphicsTools/src/RenderStateCache.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,7 @@ class ReloadableShader final : public ObjectBase<IShader>
153153
PROXY_CONST_METHOD2(m_pShader, void, GetResourceDesc, Uint32, Index, ShaderResourceDesc&, ResourceDesc)
154154
PROXY_CONST_METHOD1(m_pShader, const ShaderCodeBufferDesc*, GetConstantBufferDesc, Uint32, Index)
155155
PROXY_CONST_METHOD2(m_pShader, void, GetBytecode, const void**, ppBytecode, Uint64&, Size)
156-
157-
virtual SHADER_STATUS DILIGENT_CALL_TYPE GetStatus(bool WaitForCompletion) override final
158-
{
159-
return SHADER_STATUS_READY;
160-
}
156+
PROXY_METHOD1(m_pShader, SHADER_STATUS, GetStatus, bool, WaitForCompletion)
161157

162158
static void Create(RenderStateCacheImpl* pStateCache,
163159
IShader* pShader,
@@ -509,8 +505,9 @@ RenderStateCacheImpl::RenderStateCacheImpl(IReferenceCounters* pRe
509505
VERIFY_EXPR(pArchiverFactory != nullptr);
510506

511507
SerializationDeviceCreateInfo SerializationDeviceCI;
512-
SerializationDeviceCI.DeviceInfo = m_pDevice->GetDeviceInfo();
513-
SerializationDeviceCI.AdapterInfo = m_pDevice->GetAdapterInfo();
508+
SerializationDeviceCI.DeviceInfo = m_pDevice->GetDeviceInfo();
509+
SerializationDeviceCI.AdapterInfo = m_pDevice->GetAdapterInfo();
510+
SerializationDeviceCI.pAsyncShaderCompilationThreadPool = m_pDevice->GetShaderCompilationThreadPool();
514511

515512
switch (m_DeviceType)
516513
{

Tests/DiligentCoreAPITest/src/RenderStateCacheTest.cpp

Lines changed: 78 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626

2727
#include <functional>
28+
#include <thread>
2829

2930
#include "GPUTestingEnvironment.hpp"
3031
#include "TestingSwapChainBase.hpp"
@@ -287,6 +288,7 @@ void CreateShader(IRenderStateCache* pCache,
287288
void CreateShader(IRenderStateCache* pCache,
288289
IShaderSourceInputStreamFactory* pShaderSourceFactory,
289290
SHADER_TYPE Type,
291+
SHADER_COMPILE_FLAGS CompileFlags,
290292
const char* Name,
291293
const char* Path,
292294
bool PresentInCache,
@@ -298,6 +300,7 @@ void CreateShader(IRenderStateCache* pCache,
298300
ShaderCI.pShaderSourceStreamFactory = pShaderSourceFactory;
299301
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
300302
ShaderCI.ShaderCompiler = pEnv->GetDefaultCompiler(ShaderCI.SourceLanguage);
303+
ShaderCI.CompileFlags = CompileFlags;
301304

302305
constexpr ShaderMacro Macros[] = {{"EXTERNAL_MACROS", "2"}};
303306
ShaderCI.Macros = {Macros, _countof(Macros)};
@@ -309,18 +312,19 @@ void CreateShader(IRenderStateCache* pCache,
309312

310313
void CreateGraphicsShaders(IRenderStateCache* pCache,
311314
IShaderSourceInputStreamFactory* pShaderSourceFactory,
315+
SHADER_COMPILE_FLAGS CompileFlags,
312316
RefCntAutoPtr<IShader>& pVS,
313317
RefCntAutoPtr<IShader>& pPS,
314318
bool PresentInCache,
315319
const char* VSPath = nullptr,
316320
const char* PSPath = nullptr)
317321
{
318-
CreateShader(pCache, pShaderSourceFactory, SHADER_TYPE_VERTEX,
322+
CreateShader(pCache, pShaderSourceFactory, SHADER_TYPE_VERTEX, CompileFlags,
319323
"RenderStateCache - VS", VSPath != nullptr ? VSPath : "VertexShader.vsh",
320324
PresentInCache, pVS);
321325
ASSERT_TRUE(pVS);
322326

323-
CreateShader(pCache, pShaderSourceFactory, SHADER_TYPE_PIXEL,
327+
CreateShader(pCache, pShaderSourceFactory, SHADER_TYPE_PIXEL, CompileFlags,
324328
"RenderStateCache - PS", VSPath != nullptr ? PSPath : "PixelShader.psh",
325329
PresentInCache, pPS);
326330
ASSERT_TRUE(pPS);
@@ -329,15 +333,16 @@ void CreateGraphicsShaders(IRenderStateCache* pCache,
329333

330334
void CreateComputeShader(IRenderStateCache* pCache,
331335
IShaderSourceInputStreamFactory* pShaderSourceFactory,
336+
SHADER_COMPILE_FLAGS CompileFlags,
332337
RefCntAutoPtr<IShader>& pCS,
333338
bool PresentInCache)
334339
{
335-
CreateShader(pCache, pShaderSourceFactory, SHADER_TYPE_COMPUTE,
340+
CreateShader(pCache, pShaderSourceFactory, SHADER_TYPE_COMPUTE, CompileFlags,
336341
"RenderStateCache - CS", "ComputeShader.csh",
337342
PresentInCache, pCS);
338343
}
339344

340-
TEST(RenderStateCacheTest, CreateShader)
345+
void TestArchivingShaders(bool CompileAsync)
341346
{
342347
auto* pEnv = GPUTestingEnvironment::GetInstance();
343348
auto* pDevice = pEnv->GetDevice();
@@ -350,6 +355,7 @@ TEST(RenderStateCacheTest, CreateShader)
350355

351356
auto pTexSRV = CreateWhiteTexture();
352357

358+
const SHADER_COMPILE_FLAGS CompileFlags = CompileAsync ? SHADER_COMPILE_FLAG_ASYNCHRONOUS : SHADER_COMPILE_FLAG_NONE;
353359
for (Uint32 OptimizeGLShaders = pDevice->GetDeviceInfo().IsGLDevice() ? 0 : 1; OptimizeGLShaders < 2; ++OptimizeGLShaders)
354360
{
355361
for (Uint32 HotReload = 0; HotReload < 2; ++HotReload)
@@ -366,28 +372,28 @@ TEST(RenderStateCacheTest, CreateShader)
366372

367373
{
368374
RefCntAutoPtr<IShader> pVS, pPS;
369-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS, pPS, pData != nullptr);
375+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS, pPS, pData != nullptr);
370376
ASSERT_NE(pVS, nullptr);
371377
ASSERT_NE(pPS, nullptr);
372378

373379
VerifyGraphicsShaders(pVS, pPS, pTexSRV);
374380

375381
RefCntAutoPtr<IShader> pVS2, pPS2;
376-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS2, pPS2, true);
382+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS2, pPS2, true);
377383
EXPECT_EQ(pVS, pVS2);
378384
EXPECT_EQ(pPS, pPS);
379385
}
380386

381387
{
382388
RefCntAutoPtr<IShader> pVS, pPS;
383-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS, pPS, true);
389+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS, pPS, true);
384390
EXPECT_NE(pVS, nullptr);
385391
EXPECT_NE(pPS, nullptr);
386392
}
387393

388394
{
389395
RefCntAutoPtr<IShader> pCS;
390-
CreateComputeShader(pCache, pShaderSourceFactory, pCS, pData != nullptr);
396+
CreateComputeShader(pCache, pShaderSourceFactory, CompileFlags, pCS, pData != nullptr);
391397
EXPECT_NE(pCS, nullptr);
392398
}
393399

@@ -401,7 +407,17 @@ TEST(RenderStateCacheTest, CreateShader)
401407
}
402408
}
403409

404-
TEST(RenderStateCacheTest, BrokenShader)
410+
TEST(RenderStateCacheTest, CreateShaders)
411+
{
412+
TestArchivingShaders(false);
413+
}
414+
415+
TEST(RenderStateCacheTest, CreateShaders_Async)
416+
{
417+
TestArchivingShaders(true);
418+
}
419+
420+
void TestBrokenShader(bool CompileAsync)
405421
{
406422
auto* pEnv = GPUTestingEnvironment::GetInstance();
407423
auto* pDevice = pEnv->GetDevice();
@@ -418,20 +434,42 @@ TEST(RenderStateCacheTest, BrokenShader)
418434
ShaderCreateInfo ShaderCI;
419435
ShaderCI.Source = NotASource;
420436
ShaderCI.SourceLength = sizeof(NotASource);
437+
ShaderCI.CompileFlags = CompileAsync ? SHADER_COMPILE_FLAG_ASYNCHRONOUS : SHADER_COMPILE_FLAG_NONE;
421438

422439
constexpr ShaderMacro Macros[] = {{"EXTERNAL_MACROS", "2"}};
423440
ShaderCI.Macros = {Macros, _countof(Macros)};
424441
ShaderCI.Desc = {"Broken shader", SHADER_TYPE_VERTEX, true};
425442
RefCntAutoPtr<IShader> pShader;
426443
pEnv->SetErrorAllowance(6, "\n\nNo worries, testing broken shader...\n\n");
427444
EXPECT_FALSE(pCache->CreateShader(ShaderCI, &pShader));
428-
EXPECT_EQ(pShader, nullptr);
445+
if (CompileAsync)
446+
{
447+
EXPECT_NE(pShader, nullptr);
448+
while (pShader->GetStatus() == SHADER_STATUS_COMPILING)
449+
std::this_thread::yield();
450+
EXPECT_EQ(pShader->GetStatus(), SHADER_STATUS_FAILED);
451+
}
452+
else
453+
{
454+
EXPECT_EQ(pShader, nullptr);
455+
}
429456

430457
if (HotReload)
431458
EXPECT_EQ(pCache->Reload(), 0u);
432459
}
433460
}
434461

462+
463+
TEST(RenderStateCacheTest, BrokenShader)
464+
{
465+
TestBrokenShader(false);
466+
}
467+
468+
TEST(RenderStateCacheTest, BrokenShader_Async)
469+
{
470+
TestBrokenShader(true);
471+
}
472+
435473
RefCntAutoPtr<IRenderPass> CreateRenderPass(TEXTURE_FORMAT ColorBufferFormat)
436474
{
437475
auto* pEnv = GPUTestingEnvironment::GetInstance();
@@ -464,14 +502,16 @@ RefCntAutoPtr<IRenderPass> CreateRenderPass(TEXTURE_FORMAT ColorBufferFormat)
464502
return pRenderPass;
465503
}
466504

467-
void CreateGraphicsPSO(IRenderStateCache* pCache, bool PresentInCache, IShader* pVS, IShader* pPS, bool UseRenderPass, IPipelineState** ppPSO)
505+
void CreateGraphicsPSO(IRenderStateCache* pCache, bool PresentInCache, IShader* pVS, IShader* pPS, bool UseRenderPass, bool CompileAsync, IPipelineState** ppPSO)
468506
{
469507
auto* pEnv = GPUTestingEnvironment::GetInstance();
470508
auto* pSwapChain = pEnv->GetSwapChain();
471509

472510
GraphicsPipelineStateCreateInfo PsoCI;
473511
PsoCI.PSODesc.Name = "Render State Cache Test";
474512

513+
PsoCI.Flags = CompileAsync ? PSO_CREATE_FLAG_ASYNCHRONOUS : PSO_CREATE_FLAG_NONE;
514+
475515
PsoCI.pVS = pVS;
476516
PsoCI.pPS = pPS;
477517

@@ -517,7 +557,7 @@ void CreateGraphicsPSO(IRenderStateCache* pCache, bool PresentInCache, IShader*
517557
}
518558
}
519559

520-
void TestGraphicsPSO(bool UseRenderPass)
560+
void TestGraphicsPSO(bool UseRenderPass, bool CompileAsync = false)
521561
{
522562
auto* pEnv = GPUTestingEnvironment::GetInstance();
523563
auto* pDevice = pEnv->GetDevice();
@@ -529,13 +569,15 @@ void TestGraphicsPSO(bool UseRenderPass)
529569
pDevice->GetEngineFactory()->CreateDefaultShaderSourceStreamFactory("shaders/RenderStateCache", &pShaderSourceFactory);
530570
ASSERT_TRUE(pShaderSourceFactory);
531571

572+
SHADER_COMPILE_FLAGS CompileFlags = CompileAsync ? SHADER_COMPILE_FLAG_ASYNCHRONOUS : SHADER_COMPILE_FLAG_NONE;
573+
532574
RefCntAutoPtr<IShader> pUncachedVS, pUncachedPS;
533-
CreateGraphicsShaders(nullptr, pShaderSourceFactory, pUncachedVS, pUncachedPS, false, "VertexShader2.vsh", "PixelShader2.psh");
575+
CreateGraphicsShaders(nullptr, pShaderSourceFactory, CompileFlags, pUncachedVS, pUncachedPS, false, "VertexShader2.vsh", "PixelShader2.psh");
534576
ASSERT_NE(pUncachedVS, nullptr);
535577
ASSERT_NE(pUncachedPS, nullptr);
536578

537579
RefCntAutoPtr<IPipelineState> pRefPSO;
538-
CreateGraphicsPSO(nullptr, false, pUncachedVS, pUncachedPS, UseRenderPass, &pRefPSO);
580+
CreateGraphicsPSO(nullptr, false, pUncachedVS, pUncachedPS, UseRenderPass, /*CompileAsync = */ false, &pRefPSO);
539581
ASSERT_NE(pRefPSO, nullptr);
540582

541583
auto pTexSRV = CreateWhiteTexture();
@@ -558,12 +600,12 @@ void TestGraphicsPSO(bool UseRenderPass)
558600
ASSERT_TRUE(pCache);
559601

560602
RefCntAutoPtr<IShader> pVS1, pPS1;
561-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS1, pPS1, pData != nullptr);
603+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS1, pPS1, pData != nullptr);
562604
ASSERT_NE(pVS1, nullptr);
563605
ASSERT_NE(pPS1, nullptr);
564606

565607
RefCntAutoPtr<IPipelineState> pPSO;
566-
CreateGraphicsPSO(pCache, pData != nullptr, pVS1, pPS1, UseRenderPass, &pPSO);
608+
CreateGraphicsPSO(pCache, pData != nullptr, pVS1, pPS1, UseRenderPass, CompileAsync, &pPSO);
567609
ASSERT_NE(pPSO, nullptr);
568610
EXPECT_TRUE(pRefPSO->IsCompatibleWith(pPSO));
569611
EXPECT_TRUE(pPSO->IsCompatibleWith(pRefPSO));
@@ -573,14 +615,14 @@ void TestGraphicsPSO(bool UseRenderPass)
573615

574616
{
575617
RefCntAutoPtr<IPipelineState> pPSO2;
576-
CreateGraphicsPSO(pCache, true, pVS1, pPS1, UseRenderPass, &pPSO2);
618+
CreateGraphicsPSO(pCache, true, pVS1, pPS1, UseRenderPass, CompileAsync, &pPSO2);
577619
EXPECT_EQ(pPSO, pPSO2);
578620
}
579621

580622
if (!HotReload)
581623
{
582624
RefCntAutoPtr<IPipelineState> pPSO2;
583-
CreateGraphicsPSO(pCache, pData != nullptr, pUncachedVS, pUncachedPS, UseRenderPass, &pPSO2);
625+
CreateGraphicsPSO(pCache, pData != nullptr, pUncachedVS, pUncachedPS, UseRenderPass, CompileAsync, &pPSO2);
584626
ASSERT_NE(pPSO2, nullptr);
585627
EXPECT_TRUE(pRefPSO->IsCompatibleWith(pPSO2));
586628
EXPECT_TRUE(pPSO2->IsCompatibleWith(pRefPSO));
@@ -681,7 +723,7 @@ void CreateComputePSO(IRenderStateCache* pCache, bool PresentInCache, IShader* p
681723
}
682724
}
683725

684-
void TestComputePSO(bool UseSignature)
726+
void TestComputePSO(bool UseSignature, bool CompileAsync = false)
685727
{
686728
auto* pEnv = GPUTestingEnvironment::GetInstance();
687729
auto* pDevice = pEnv->GetDevice();
@@ -696,10 +738,12 @@ void TestComputePSO(bool UseSignature)
696738
pDevice->GetEngineFactory()->CreateDefaultShaderSourceStreamFactory("shaders/RenderStateCache", &pShaderSourceFactory);
697739
ASSERT_TRUE(pShaderSourceFactory);
698740

741+
const SHADER_COMPILE_FLAGS CompileFlags = CompileAsync ? SHADER_COMPILE_FLAG_ASYNCHRONOUS : SHADER_COMPILE_FLAG_NONE;
742+
699743
RefCntAutoPtr<IPipelineState> pRefPSO;
700744
{
701745
RefCntAutoPtr<IShader> pUncachedCS;
702-
CreateComputeShader(nullptr, pShaderSourceFactory, pUncachedCS, false);
746+
CreateComputeShader(nullptr, pShaderSourceFactory, CompileFlags, pUncachedCS, false);
703747
ASSERT_NE(pUncachedCS, nullptr);
704748

705749
CreateComputePSO(nullptr, false, pUncachedCS, UseSignature, &pRefPSO);
@@ -719,7 +763,7 @@ void TestComputePSO(bool UseSignature)
719763
ASSERT_TRUE(pCache);
720764

721765
RefCntAutoPtr<IShader> pCS;
722-
CreateComputeShader(pCache, pShaderSourceFactory, pCS, pData != nullptr);
766+
CreateComputeShader(pCache, pShaderSourceFactory, CompileFlags, pCS, pData != nullptr);
723767
ASSERT_NE(pCS, nullptr);
724768

725769
RefCntAutoPtr<IPipelineState> pPSO;
@@ -955,8 +999,10 @@ TEST(RenderStateCacheTest, AppendData)
955999

9561000
auto pWhiteTexture = CreateWhiteTexture();
9571001

958-
constexpr bool UseSignature = false;
959-
constexpr bool UseRenderPass = false;
1002+
constexpr bool UseSignature = false;
1003+
constexpr bool UseRenderPass = false;
1004+
constexpr bool CompileAsync = false;
1005+
const SHADER_COMPILE_FLAGS CompileFlags = CompileAsync ? SHADER_COMPILE_FLAG_ASYNCHRONOUS : SHADER_COMPILE_FLAG_NONE;
9601006

9611007
for (Uint32 HotReload = 0; HotReload < 2; ++HotReload)
9621008
{
@@ -965,7 +1011,7 @@ TEST(RenderStateCacheTest, AppendData)
9651011
auto pCache = CreateCache(pDevice, HotReload);
9661012

9671013
RefCntAutoPtr<IShader> pCS;
968-
CreateComputeShader(pCache, pShaderSourceFactory, pCS, false);
1014+
CreateComputeShader(pCache, pShaderSourceFactory, CompileFlags, pCS, false);
9691015
ASSERT_NE(pCS, nullptr);
9701016

9711017
RefCntAutoPtr<IPipelineState> pPSO;
@@ -981,12 +1027,12 @@ TEST(RenderStateCacheTest, AppendData)
9811027
auto pCache = CreateCache(pDevice, HotReload, pData);
9821028

9831029
RefCntAutoPtr<IShader> pVS1, pPS1;
984-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS1, pPS1, pass > 0);
1030+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS1, pPS1, pass > 0);
9851031
ASSERT_NE(pVS1, nullptr);
9861032
ASSERT_NE(pPS1, nullptr);
9871033

9881034
RefCntAutoPtr<IPipelineState> pPSO;
989-
CreateGraphicsPSO(pCache, pass > 0, pVS1, pPS1, UseRenderPass, &pPSO);
1035+
CreateGraphicsPSO(pCache, pass > 0, pVS1, pPS1, UseRenderPass, CompileAsync, &pPSO);
9901036
ASSERT_NE(pPSO, nullptr);
9911037

9921038
VerifyGraphicsPSO(pPSO, nullptr, pWhiteTexture, UseRenderPass);
@@ -1117,6 +1163,8 @@ void TestPipelineReload(bool UseRenderPass, bool CreateSrbBeforeReload = false,
11171163
pCtx->TransitionResourceStates(_countof(Barriers), Barriers);
11181164
}
11191165

1166+
SHADER_COMPILE_FLAGS CompileFlags = SHADER_COMPILE_FLAG_NONE;
1167+
11201168
RefCntAutoPtr<IDataBlob> pData;
11211169
for (Uint32 pass = 0; pass < 3; ++pass)
11221170
{
@@ -1128,7 +1176,7 @@ void TestPipelineReload(bool UseRenderPass, bool CreateSrbBeforeReload = false,
11281176
ASSERT_TRUE(pCache);
11291177

11301178
RefCntAutoPtr<IShader> pVS, pPS;
1131-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS, pPS, pData != nullptr, "VertexShaderRld.vsh", "PixelShaderRld.psh");
1179+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS, pPS, pData != nullptr, "VertexShaderRld.vsh", "PixelShaderRld.psh");
11321180
ASSERT_NE(pVS, nullptr);
11331181
ASSERT_NE(pPS, nullptr);
11341182

@@ -1371,7 +1419,8 @@ TEST(RenderStateCacheTest, Reload_Signatures2)
13711419
pDevice->GetEngineFactory()->CreateDefaultShaderSourceStreamFactory("shaders/RenderStateCache/Reload2;shaders/RenderStateCache", &pShaderReloadFactory);
13721420
ASSERT_TRUE(pShaderSourceFactory);
13731421

1374-
constexpr auto HotReload = true;
1422+
constexpr bool HotReload = true;
1423+
SHADER_COMPILE_FLAGS CompileFlags = SHADER_COMPILE_FLAG_NONE;
13751424

13761425
for (Uint32 use_different_signatures = 0; use_different_signatures < 2; ++use_different_signatures)
13771426
{
@@ -1386,7 +1435,7 @@ TEST(RenderStateCacheTest, Reload_Signatures2)
13861435
ASSERT_TRUE(pCache);
13871436

13881437
RefCntAutoPtr<IShader> pVS, pPS;
1389-
CreateGraphicsShaders(pCache, pShaderSourceFactory, pVS, pPS, pData != nullptr, "VertexShader3.vsh", "PixelShader.psh");
1438+
CreateGraphicsShaders(pCache, pShaderSourceFactory, CompileFlags, pVS, pPS, pData != nullptr, "VertexShader3.vsh", "PixelShader.psh");
13901439
ASSERT_NE(pVS, nullptr);
13911440
ASSERT_NE(pPS, nullptr);
13921441

0 commit comments

Comments
 (0)