Skip to content

Commit 5c5b091

Browse files
Add test for inline constants in render state cache
1 parent f99e3dd commit 5c5b091

File tree

1 file changed

+229
-0
lines changed

1 file changed

+229
-0
lines changed

Tests/DiligentCoreAPITest/src/InlineConstantsTest.cpp

Lines changed: 229 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,229 @@ 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+
auto* pEnv = GPUTestingEnvironment::GetInstance();
586+
auto* 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+
const auto ColorBufferFormat = pSwapChain->GetDesc().ColorBufferFormat;
595+
596+
PsoCI.GraphicsPipeline.NumRenderTargets = 1;
597+
PsoCI.GraphicsPipeline.RTVFormats[0] = ColorBufferFormat;
598+
599+
PsoCI.GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
600+
601+
static ShaderResourceVariableDesc Vars[] =
602+
{
603+
{SHADER_TYPE_VERTEX, "cbInlinePositions", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_FLAG_INLINE_CONSTANTS},
604+
{SHADER_TYPE_VERTEX, "cbInlineColors", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_FLAG_INLINE_CONSTANTS},
605+
};
606+
PsoCI.PSODesc.ResourceLayout.Variables = Vars;
607+
PsoCI.PSODesc.ResourceLayout.NumVariables = _countof(Vars);
608+
609+
if (pCache != nullptr)
610+
{
611+
bool PSOFound = pCache->CreateGraphicsPipelineState(PsoCI, ppPSO);
612+
EXPECT_EQ(PSOFound, PresentInCache);
613+
}
614+
else
615+
{
616+
EXPECT_FALSE(PresentInCache);
617+
pEnv->GetDevice()->CreateGraphicsPipelineState(PsoCI, ppPSO);
618+
ASSERT_NE(*ppPSO, nullptr);
619+
}
620+
621+
if (*ppPSO != nullptr && (*ppPSO)->GetStatus() == PIPELINE_STATE_STATUS_READY)
622+
{
623+
const auto& Desc = (*ppPSO)->GetDesc();
624+
EXPECT_EQ(PsoCI.PSODesc, Desc);
625+
}
626+
}
627+
628+
void InlineConstants::VerifyPSOFromCache(IPipelineState* pPSO,
629+
IShaderResourceBinding* pSRB)
630+
{
631+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
632+
IDeviceContext* pContext = pEnv->GetDeviceContext();
633+
ISwapChain* pSwapChain = pEnv->GetSwapChain();
634+
635+
const float ClearColor[] = {sm_Rnd(), sm_Rnd(), sm_Rnd(), sm_Rnd()};
636+
RenderDrawCommandReference(pSwapChain, ClearColor);
637+
638+
ITextureView* pRTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
639+
pContext->SetRenderTargets(1, pRTVs, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
640+
pContext->ClearRenderTarget(pRTVs[0], ClearColor, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
641+
642+
RefCntAutoPtr<IShaderResourceBinding> _pSRB;
643+
if (pSRB == nullptr)
644+
{
645+
pPSO->CreateShaderResourceBinding(&_pSRB, true);
646+
pSRB = _pSRB;
647+
}
648+
649+
pContext->SetPipelineState(pPSO);
650+
pContext->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
651+
652+
IShaderResourceVariable* pColVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlineColors");
653+
ASSERT_TRUE(pColVar);
654+
pColVar->SetInlineConstants(g_Colors, 0, kNumColConstants);
655+
656+
IShaderResourceVariable* pPosVar = pSRB->GetVariableByName(SHADER_TYPE_VERTEX, "cbInlinePositions");
657+
ASSERT_TRUE(pPosVar);
658+
pPosVar->SetInlineConstants(g_Positions, 0, kNumPosConstants / 2);
659+
pContext->Draw({3, DRAW_FLAG_VERIFY_ALL});
660+
661+
pPosVar->SetInlineConstants(g_Positions[0].Data() + kNumPosConstants / 2, 0, kNumPosConstants / 2);
662+
pContext->Draw({3, DRAW_FLAG_VERIFY_ALL});
663+
664+
Present();
665+
}
666+
667+
TEST_F(InlineConstants, RenderStateCache)
668+
{
669+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
670+
IRenderDevice* pDevice = pEnv->GetDevice();
671+
672+
if (pDevice->GetDeviceInfo().Type != RENDER_DEVICE_TYPE_D3D12)
673+
{
674+
GTEST_SKIP();
675+
}
676+
677+
GPUTestingEnvironment::ScopedReset AutoReset;
678+
679+
RefCntAutoPtr<IShaderSourceInputStreamFactory> pShaderSourceFactory;
680+
pDevice->GetEngineFactory()->CreateDefaultShaderSourceStreamFactory("shaders/RenderStateCache", &pShaderSourceFactory);
681+
ASSERT_TRUE(pShaderSourceFactory);
682+
683+
RefCntAutoPtr<IShader> pUncachedVS, pUncachedPS;
684+
CreateShadersFromCache(nullptr, false, &pUncachedVS, &pUncachedPS);
685+
ASSERT_NE(pUncachedVS, nullptr);
686+
ASSERT_NE(pUncachedPS, nullptr);
687+
688+
RefCntAutoPtr<IPipelineState> pRefPSO;
689+
CreatePSOFromCache(nullptr, false, pUncachedVS, pUncachedPS, &pRefPSO);
690+
ASSERT_NE(pRefPSO, nullptr);
691+
692+
RefCntAutoPtr<IShaderResourceBinding> pRefSRB;
693+
pRefPSO->CreateShaderResourceBinding(&pRefSRB);
694+
695+
RefCntAutoPtr<IDataBlob> pData;
696+
for (Uint32 pass = 0; pass < 3; ++pass)
697+
{
698+
// 0: empty cache
699+
// 1: loaded cache
700+
// 2: reloaded cache (loaded -> stored -> loaded)
701+
702+
auto pCache = CreateCache(pDevice, false, false, pData);
703+
ASSERT_TRUE(pCache);
704+
705+
RefCntAutoPtr<IShader> pVS1, pPS1;
706+
CreateShadersFromCache(pCache, pData != nullptr, &pVS1, &pPS1);
707+
ASSERT_NE(pVS1, nullptr);
708+
ASSERT_NE(pPS1, nullptr);
709+
710+
RefCntAutoPtr<IPipelineState> pPSO;
711+
CreatePSOFromCache(pCache, pData != nullptr, pVS1, pPS1, &pPSO);
712+
ASSERT_NE(pPSO, nullptr);
713+
ASSERT_EQ(pPSO->GetStatus(), PIPELINE_STATE_STATUS_READY);
714+
EXPECT_TRUE(pRefPSO->IsCompatibleWith(pPSO));
715+
EXPECT_TRUE(pPSO->IsCompatibleWith(pRefPSO));
716+
717+
VerifyPSOFromCache(pPSO, nullptr);
718+
VerifyPSOFromCache(pPSO, pRefSRB);
719+
720+
{
721+
RefCntAutoPtr<IPipelineState> pPSO2;
722+
CreatePSOFromCache(pCache, true, pVS1, pPS1, &pPSO2);
723+
EXPECT_EQ(pPSO, pPSO2);
724+
}
725+
726+
{
727+
RefCntAutoPtr<IPipelineState> pPSO2;
728+
CreatePSOFromCache(pCache, pData != nullptr, pUncachedVS, pUncachedPS, &pPSO2);
729+
ASSERT_NE(pPSO2, nullptr);
730+
ASSERT_EQ(pPSO2->GetStatus(), PIPELINE_STATE_STATUS_READY);
731+
EXPECT_TRUE(pRefPSO->IsCompatibleWith(pPSO2));
732+
EXPECT_TRUE(pPSO2->IsCompatibleWith(pRefPSO));
733+
VerifyPSOFromCache(pPSO2, nullptr);
734+
VerifyPSOFromCache(pPSO2, pRefSRB);
735+
}
736+
737+
pData.Release();
738+
pCache->WriteToBlob(pass == 0 ? kCacheContentVersion : ~0u, &pData);
739+
}
740+
}
741+
513742
} // namespace

0 commit comments

Comments
 (0)