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,
287288void 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
310313void 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
330334void 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\n No 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+
435473RefCntAutoPtr<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