Skip to content

Commit 2f706ee

Browse files
Add test for inline constants in render state cache
1 parent f99e3dd commit 2f706ee

File tree

1 file changed

+236
-0
lines changed

1 file changed

+236
-0
lines changed

Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "gtest/gtest.h"
3030

31+
#include "RenderStateCache.hpp"
3132
#include "GraphicsTypesX.hpp"
3233
#include "FastRand.hpp"
3334

@@ -151,6 +152,9 @@ class InlineConstants : public ::testing::Test
151152
pContext->InvalidateState();
152153
}
153154

155+
static void VerifyPSOFromCache(IPipelineState* pPSO,
156+
IShaderResourceBinding* pSRB);
157+
154158
struct Resources
155159
{
156160
RefCntAutoPtr<IShader> pVS;
@@ -510,4 +514,236 @@ TEST_F(InlineConstants, TwoResourceSignatures)
510514
TestSignatures(2);
511515
}
512516

517+
constexpr Uint32 kCacheContentVersion = 7;
518+
519+
RefCntAutoPtr<IRenderStateCache> CreateCache(IRenderDevice* pDevice,
520+
bool HotReload,
521+
bool OptimizeGLShaders,
522+
IDataBlob* pCacheData = nullptr,
523+
IShaderSourceInputStreamFactory* pShaderReloadFactory = nullptr)
524+
{
525+
RenderStateCacheCreateInfo CacheCI{
526+
pDevice,
527+
GPUTestingEnvironment::GetInstance()->GetArchiverFactory(),
528+
RENDER_STATE_CACHE_LOG_LEVEL_VERBOSE,
529+
RENDER_STATE_CACHE_FILE_HASH_MODE_BY_CONTENT,
530+
HotReload,
531+
};
532+
533+
RefCntAutoPtr<IRenderStateCache> pCache;
534+
CreateRenderStateCache(CacheCI, &pCache);
535+
536+
if (pCacheData != nullptr)
537+
pCache->Load(pCacheData, kCacheContentVersion);
538+
539+
return pCache;
540+
}
541+
542+
543+
void CreateShadersFromCache(IRenderStateCache* pCache, bool PresentInCache, IShader** ppVS, IShader** ppPS)
544+
{
545+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
546+
IRenderDevice* pDevice = pEnv->GetDevice();
547+
548+
ShaderCreateInfo ShaderCI;
549+
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
550+
ShaderCI.ShaderCompiler = pEnv->GetDefaultCompiler(ShaderCI.SourceLanguage);
551+
552+
{
553+
ShaderCI.Desc = {"Inline constants test", SHADER_TYPE_VERTEX, true};
554+
ShaderCI.EntryPoint = "main";
555+
ShaderCI.Source = HLSL::InlineConstantsTest_VS.c_str();
556+
if (pCache != nullptr)
557+
{
558+
EXPECT_EQ(pCache->CreateShader(ShaderCI, ppVS), PresentInCache);
559+
}
560+
else
561+
{
562+
pDevice->CreateShader(ShaderCI, ppVS);
563+
EXPECT_EQ(PresentInCache, false);
564+
}
565+
}
566+
567+
{
568+
ShaderCI.Desc = {"Inline constants test", SHADER_TYPE_PIXEL, true};
569+
ShaderCI.EntryPoint = "main";
570+
ShaderCI.Source = HLSL::DrawTest_PS.c_str();
571+
if (pCache != nullptr)
572+
{
573+
EXPECT_EQ(pCache->CreateShader(ShaderCI, ppPS), PresentInCache);
574+
}
575+
else
576+
{
577+
pDevice->CreateShader(ShaderCI, ppPS);
578+
EXPECT_EQ(PresentInCache, false);
579+
}
580+
}
581+
}
582+
583+
void CreatePSOFromCache(IRenderStateCache* pCache, bool PresentInCache, IShader* pVS, IShader* pPS, IPipelineState** ppPSO)
584+
{
585+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
586+
ISwapChain* pSwapChain = pEnv->GetSwapChain();
587+
588+
GraphicsPipelineStateCreateInfo PsoCI;
589+
PsoCI.PSODesc.Name = "Render State Cache Test";
590+
591+
PsoCI.pVS = pVS;
592+
PsoCI.pPS = pPS;
593+
594+
PsoCI.GraphicsPipeline.NumRenderTargets = 1;
595+
PsoCI.GraphicsPipeline.RTVFormats[0] = pSwapChain->GetDesc().ColorBufferFormat;
596+
597+
PsoCI.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
598+
599+
static ShaderResourceVariableDesc Vars[] =
600+
{
601+
{SHADER_TYPE_VERTEX, "cbInlinePositions", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_FLAG_INLINE_CONSTANTS},
602+
{SHADER_TYPE_VERTEX, "cbInlineColors", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_FLAG_INLINE_CONSTANTS},
603+
};
604+
PsoCI.PSODesc.ResourceLayout.Variables = Vars;
605+
PsoCI.PSODesc.ResourceLayout.NumVariables = _countof(Vars);
606+
607+
if (pCache != nullptr)
608+
{
609+
bool PSOFound = pCache->CreateGraphicsPipelineState(PsoCI, ppPSO);
610+
EXPECT_EQ(PSOFound, PresentInCache);
611+
}
612+
else
613+
{
614+
EXPECT_FALSE(PresentInCache);
615+
pEnv->GetDevice()->CreateGraphicsPipelineState(PsoCI, ppPSO);
616+
ASSERT_NE(*ppPSO, nullptr);
617+
}
618+
619+
if (*ppPSO != nullptr && (*ppPSO)->GetStatus() == PIPELINE_STATE_STATUS_READY)
620+
{
621+
const PipelineStateDesc& Desc = (*ppPSO)->GetDesc();
622+
EXPECT_EQ(PsoCI.PSODesc, Desc);
623+
}
624+
}
625+
626+
void InlineConstants::VerifyPSOFromCache(IPipelineState* pPSO,
627+
IShaderResourceBinding* pSRB)
628+
{
629+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
630+
IDeviceContext* pContext = pEnv->GetDeviceContext();
631+
ISwapChain* pSwapChain = pEnv->GetSwapChain();
632+
633+
const float ClearColor[] = {sm_Rnd(), sm_Rnd(), sm_Rnd(), sm_Rnd()};
634+
RenderDrawCommandReference(pSwapChain, ClearColor);
635+
636+
ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
637+
pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
638+
pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
639+
640+
RefCntAutoPtr<IShaderResourceBinding> _pSRB;
641+
if (pSRB == nullptr)
642+
{
643+
pPSO->CreateShaderResourceBinding(&_pSRB, true);
644+
pSRB = _pSRB;
645+
}
646+
647+
pContext->SetPipelineState(pPSO);
648+
pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
649+
650+
IShaderResourceVariable* pColVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors");
651+
ASSERT_TRUE(pColVar);
652+
pColVar->SetInlineConstants(g_Colors, 0, kNumColConstants);
653+
654+
IShaderResourceVariable* pPosVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions");
655+
ASSERT_TRUE(pPosVar);
656+
pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants / 2);
657+
pContext->Draw({3, DRAW_FLAG_VERIFY_ALL});
658+
659+
pPosVar->SetInlineConstants(g_Positions[0].Data() + kNumPosConstants / 2, 0, kNumPosConstants / 2);
660+
pContext->Draw({3, DRAW_FLAG_VERIFY_ALL});
661+
662+
Present();
663+
}
664+
665+
TEST_F(InlineConstants, RenderStateCache)
666+
{
667+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
668+
IRenderDevice* pDevice = pEnv->GetDevice();
669+
670+
if (pDevice->GetDeviceInfo().Type != RENDER_DEVICE_TYPE_D3D12)
671+
{
672+
GTEST_SKIP();
673+
}
674+
675+
GPUTestingEnvironment::ScopedReset AutoReset;
676+
677+
RefCntAutoPtr<IShaderSourceInputStreamFactory> pShaderSourceFactory;
678+
pDevice->GetEngineFactory()->CreateDefaultShaderSourceStreamFactory("shaders/RenderStateCache", &pShaderSourceFactory);
679+
ASSERT_TRUE(pShaderSourceFactory);
680+
681+
RefCntAutoPtr<IShader> pUncachedVS, pUncachedPS;
682+
CreateShadersFromCache(nullptr, false, &pUncachedVS, &pUncachedPS);
683+
ASSERT_NE(pUncachedVS, nullptr);
684+
ASSERT_NE(pUncachedPS, nullptr);
685+
686+
RefCntAutoPtr<IPipelineState> pRefPSO;
687+
CreatePSOFromCache(nullptr, false, pUncachedVS, pUncachedPS, &pRefPSO);
688+
ASSERT_NE(pRefPSO, nullptr);
689+
690+
RefCntAutoPtr<IShaderResourceBinding> pRefSRB;
691+
pRefPSO->CreateShaderResourceBinding(&pRefSRB);
692+
693+
RefCntAutoPtr<IDataBlob> pData;
694+
for (Uint32 pass = 0; pass < 3; ++pass)
695+
{
696+
// 0: empty cache
697+
// 1: loaded cache
698+
// 2: reloaded cache (loaded -> stored -> loaded)
699+
700+
RefCntAutoPtr<IRenderStateCache> pCache = CreateCache(pDevice, false, false, pData);
701+
ASSERT_TRUE(pCache);
702+
703+
RefCntAutoPtr<IShader> pVS1, pPS1;
704+
CreateShadersFromCache(pCache, pData != nullptr, &pVS1, &pPS1);
705+
ASSERT_NE(pVS1, nullptr);
706+
ASSERT_NE(pPS1, nullptr);
707+
708+
RefCntAutoPtr<IPipelineState> pPSO;
709+
CreatePSOFromCache(pCache, pData != nullptr, pVS1, pPS1, &pPSO);
710+
ASSERT_NE(pPSO, nullptr);
711+
ASSERT_EQ(pPSO->GetStatus(), PIPELINE_STATE_STATUS_READY);
712+
EXPECT_TRUE(pRefPSO->IsCompatibleWith(pPSO));
713+
EXPECT_TRUE(pPSO->IsCompatibleWith(pRefPSO));
714+
715+
VerifyPSOFromCache(pPSO, nullptr);
716+
VerifyPSOFromCache(pPSO, pRefSRB);
717+
718+
{
719+
RefCntAutoPtr<IPipelineState> pPSO2;
720+
CreatePSOFromCache(pCache, true, pVS1, pPS1, &pPSO2);
721+
EXPECT_EQ(pPSO, pPSO2);
722+
}
723+
724+
{
725+
RefCntAutoPtr<IPipelineState> pPSO2;
726+
727+
bool PresentInCache = pData != nullptr;
728+
#if !DILIGENT_DEBUG
729+
if (pDevice->GetDeviceInfo().IsD3DDevice())
730+
{
731+
// For some reason, hash computation consistency depends on D3DCOMPILE_DEBUG flag and differs between debug and release builds
732+
PresentInCache = true;
733+
}
734+
#endif
735+
CreatePSOFromCache(pCache, PresentInCache, pUncachedVS, pUncachedPS, &pPSO2);
736+
ASSERT_NE(pPSO2, nullptr);
737+
ASSERT_EQ(pPSO2->GetStatus(), PIPELINE_STATE_STATUS_READY);
738+
EXPECT_TRUE(pRefPSO->IsCompatibleWith(pPSO2));
739+
EXPECT_TRUE(pPSO2->IsCompatibleWith(pRefPSO));
740+
VerifyPSOFromCache(pPSO2, nullptr);
741+
VerifyPSOFromCache(pPSO2, pRefSRB);
742+
}
743+
744+
pData.Release();
745+
pCache->WriteToBlob(pass == 0 ? kCacheContentVersion : ~0u, &pData);
746+
}
747+
}
748+
513749
} // namespace

0 commit comments

Comments
 (0)