| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/UnitTest/TestTypes.h>
- #include <Atom/RPI.Public/GpuQuery/GpuQueryTypes.h>
- #include <Atom/RPI.Public/GpuQuery/GpuQuerySystem.h>
- #include <Atom/RPI.Public/GpuQuery/TimestampQueryPool.h>
- #include <Atom/RPI.Public/GpuQuery/GpuQuerySystemInterface.h>
- #include <Atom/RHI/BufferScopeAttachment.h>
- #include <Atom/RHI/FrameGraph.h>
- #include <Atom/RHI/QueryPool.h>
- #include <AzTest/AzTest.h>
- #include <Common/RPITestFixture.h>
- namespace UnitTest
- {
- using namespace AZ;
- using namespace AZ::RPI;
- class GpuQueryTests
- : public RPITestFixture
- {
- void SetUp() final
- {
- RPITestFixture::SetUp();
- }
- void TearDown() final
- {
- RPITestFixture::TearDown();
- }
- };
- // Unit test the RPI::QueryPool
- TEST_F(GpuQueryTests, TestQueryPools)
- {
- const uint32_t QueryCount = 1024u;
- const uint32_t QueriesPerInstance = 1u;
- const RHI::QueryType Type = RHI::QueryType::Occlusion;
- const RHI::PipelineStatisticsFlags StatisticsFlags = RHI::PipelineStatisticsFlags::None;
- const uint32_t OcclusionQueryResultSize = sizeof(uint64_t);
- const RHI::FrameGraphExecuteContext::Descriptor desc = {};
- RHI::FrameGraphExecuteContext context(desc);
- // Setup the FrameGraph
- RHI::Scope scope;
- scope.Init(RHI::ScopeId("StubScope"));
- RHI::FrameGraph frameGraph;
- frameGraph.BeginScope(scope);
- AZStd::unique_ptr<RPI::QueryPool> queryPool = RPI::QueryPool::CreateQueryPool(QueryCount, QueriesPerInstance, Type, StatisticsFlags);
- const uint32_t resultSize = queryPool->GetQueryResultSize();
- EXPECT_EQ(resultSize, OcclusionQueryResultSize);
- // Test valid Queries
- {
- RHI::Ptr<RPI::Query> query = queryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- }
- // Test adding to the FrameGraph multiple times with one Query within a single frame
- {
- RHI::Ptr<RPI::Query> query = queryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- QueryResultCode resultCode = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- resultCode = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode, QueryResultCode::Fail);
- // Next frame
- queryPool->Update();
- }
- // Test recording the same Query in different frames
- {
- RHI::Ptr<RPI::Query> query = queryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- QueryResultCode resultCode = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- // Next frame
- queryPool->Update();
- resultCode = query->BeginQuery(context);
- EXPECT_EQ(resultCode, QueryResultCode::Fail);
- }
- // Test Query result
- {
- // Occlusion QueryPool result size is sizeof(uint64_t)
- EXPECT_EQ(queryPool->GetQueryResultSize(), sizeof(uint64_t));
- }
- // Test get result with invalid size
- {
- RHI::Ptr<RPI::Query> query = queryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- QueryResultCode resultCode = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- void* data = nullptr;
- // Query type of the pool is occlusion, which expects a result size of sizeof(uint64_t).
- resultCode = query->GetLatestResult(data, sizeof(uint32_t));
- EXPECT_EQ(resultCode, QueryResultCode::Fail);
- }
- // Test going over QueryPool limit
- {
- // Temporary QueryPool with a limit of 1 Query
- AZStd::unique_ptr<RPI::QueryPool> tempRpiQueryPool = RPI::QueryPool::CreateQueryPool(1u, QueriesPerInstance, Type, StatisticsFlags);
- RHI::Ptr<RPI::Query> query = tempRpiQueryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- RHI::Ptr<RPI::Query> query1 = tempRpiQueryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(!query1.get());
- }
- // Test different Scopes for Begin() and End()
- {
- RHI::FrameGraphExecuteContext::Descriptor desc2;
- desc2.m_scopeId = RHI::ScopeId("Test");
- desc2.m_commandListIndex = 0;
- desc2.m_commandListCount = 1;
- desc2.m_commandList = nullptr;
- RHI::FrameGraphExecuteContext context2(desc2);
- RHI::Ptr<RPI::Query> query = queryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- QueryResultCode resultCode = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- resultCode = query->BeginQuery(context);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- resultCode = query->EndQuery(context2);
- EXPECT_EQ(resultCode, QueryResultCode::Fail);
- }
- }
- // Test occlusion QueryPool
- TEST_F(GpuQueryTests, TestOcclusionQueryPool)
- {
- const uint32_t QueryCount = 1024u;
- const uint32_t QueriesPerInstance = 1u;
- const RHI::QueryType Type = RHI::QueryType::Occlusion;
- const RHI::PipelineStatisticsFlags StatisticsFlags = RHI::PipelineStatisticsFlags::None;
- const uint32_t ResultSize = sizeof(uint64_t);
- uint64_t mockData;
- RHI::FrameGraphExecuteContext::Descriptor desc = {};
- uint64_t dummyCommandList;
- desc.m_commandList = reinterpret_cast<RHI::CommandList*>(&dummyCommandList);
- RHI::FrameGraphExecuteContext context(desc);
- RHI::Scope scope;
- scope.Init(RHI::ScopeId("StubScope"));
- RHI::FrameGraph frameGraph;
- frameGraph.BeginScope(scope);
- // Test get result of a Query successfully
- {
- const uint32_t LoopCount = 4u;
- QueryResultCode resultCode;
- AZStd::unique_ptr<RPI::QueryPool> tempRpiQueryPool = RPI::QueryPool::CreateQueryPool(QueryCount, QueriesPerInstance, Type, StatisticsFlags);
- RHI::Ptr<RPI::Query> query = tempRpiQueryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- for (uint32_t i = 0u; i < LoopCount; i++)
- {
- QueryResultCode resultCode2;
- resultCode2 = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- resultCode2 = query->BeginQuery(context);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- resultCode2 = query->EndQuery(context);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- tempRpiQueryPool->Update();
- }
- void* data = reinterpret_cast<void*>(&mockData);
- resultCode = query->GetLatestResult(data, ResultSize);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- resultCode = query->GetLatestResultAndWait(data, ResultSize);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- }
- }
- // Test statistics QueryPool
- TEST_F(GpuQueryTests, TestStatisticsQueryPool)
- {
- const uint32_t QueryCount = 1024u;
- const uint32_t QueriesPerInstance = 1u;
- const RHI::QueryType Type = RHI::QueryType::PipelineStatistics;
- const RHI::PipelineStatisticsFlags StatisticsFlags =
- RHI::PipelineStatisticsFlags::CInvocations |
- RHI::PipelineStatisticsFlags::CPrimitives |
- RHI::PipelineStatisticsFlags::CSInvocations |
- RHI::PipelineStatisticsFlags::DSInvocations;
- const uint32_t ResultSize = sizeof(uint64_t) * 4u;
- uint64_t mockData;
- RHI::FrameGraphExecuteContext::Descriptor desc = {};
- uint64_t dummyCommandList;
- desc.m_commandList = reinterpret_cast<RHI::CommandList*>(&dummyCommandList);
- RHI::FrameGraphExecuteContext context(desc);
- RHI::Scope scope;
- scope.Init(RHI::ScopeId("StubScope"));
- RHI::FrameGraph frameGraph;
- frameGraph.BeginScope(scope);
- AZStd::unique_ptr<RPI::QueryPool> queryPool = RPI::QueryPool::CreateQueryPool(QueryCount, QueriesPerInstance, Type, StatisticsFlags);
- // Test expected result size
- {
- const uint32_t resultSize = queryPool->GetQueryResultSize();
- EXPECT_EQ(resultSize, ResultSize);
- }
- // Test get result with invalid size
- {
- RHI::Ptr<RPI::Query> query = queryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- QueryResultCode resultCode = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- void* data = nullptr;
- // Query type of the pool is statistics, which expects a result size of sizeof(uint64_t) * number of active flags.
- resultCode = query->GetLatestResult(data, sizeof(uint64_t) * 3u);
- EXPECT_EQ(resultCode, QueryResultCode::Fail);
- }
- // Test get result of a Query successfully
- {
- const uint32_t LoopCount = 4u;
- QueryResultCode resultCode;
- AZStd::unique_ptr<RPI::QueryPool> tempRpiQueryPool = RPI::QueryPool::CreateQueryPool(QueryCount, QueriesPerInstance, Type, StatisticsFlags);
- RHI::Ptr<RPI::Query> query = tempRpiQueryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- for (uint32_t i = 0u; i < LoopCount; i++)
- {
- QueryResultCode resultCode2;
- resultCode2 = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- resultCode2 = query->BeginQuery(context);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- resultCode2 = query->EndQuery(context);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- tempRpiQueryPool->Update();
- }
- void* data = reinterpret_cast<void*>(&mockData);
- resultCode = query->GetLatestResult(data, ResultSize);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- resultCode = query->GetLatestResultAndWait(data, ResultSize);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- }
- }
- // Test timestamp QueryPool
- TEST_F(GpuQueryTests, TestTimestampQueryPool)
- {
- const uint32_t QueryCount = 1024u;
- const uint32_t ResultSize = sizeof(uint64_t) * 2u;
- uint64_t mockData;
- RHI::FrameGraphExecuteContext::Descriptor desc = {};
- uint64_t dummyCommandList;
- desc.m_commandList = reinterpret_cast<RHI::CommandList*>(&dummyCommandList);
- RHI::FrameGraphExecuteContext context(desc);
- RHI::Scope scope;
- scope.Init(RHI::ScopeId("StubScope"));
- RHI::FrameGraph frameGraph;
- frameGraph.BeginScope(scope);
- // Test get result of a Query successfully
- {
- const uint32_t LoopCount = 4u;
- QueryResultCode resultCode;
- AZStd::unique_ptr<RPI::QueryPool> tempRpiQueryPool = RPI::TimestampQueryPool::CreateTimestampQueryPool(QueryCount);
- RHI::Ptr<RPI::Query> query = tempRpiQueryPool->CreateQuery(RHI::QueryPoolScopeAttachmentType::Global, RHI::ScopeAttachmentAccess::Write);
- EXPECT_TRUE(query.get());
- for (uint32_t i = 0u; i < LoopCount; i++)
- {
- QueryResultCode resultCode2;
- resultCode2 = query->AddToFrameGraph(frameGraph);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- resultCode2 = query->BeginQuery(context);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- resultCode2 = query->EndQuery(context);
- EXPECT_EQ(resultCode2, QueryResultCode::Success);
- tempRpiQueryPool->Update();
- }
- void* data = reinterpret_cast<void*>(&mockData);
- resultCode = query->GetLatestResult(data, ResultSize);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- resultCode = query->GetLatestResultAndWait(data, ResultSize);
- EXPECT_EQ(resultCode, QueryResultCode::Success);
- }
- }
- }; // namespace UnitTest
|