Skip to content

Commit

Permalink
Add support GpuTimer for LLGI (#1008)
Browse files Browse the repository at this point in the history
  • Loading branch information
ueshita authored Mar 26, 2024
1 parent df63a09 commit 96d747a
Show file tree
Hide file tree
Showing 36 changed files with 488 additions and 81 deletions.
2 changes: 1 addition & 1 deletion Dev/Cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.15)

if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum OS X deployment version" FORCE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
endif()

project(Effekseer C CXX)
Expand Down
5 changes: 5 additions & 0 deletions Dev/Cpp/Effekseer/Effekseer/Effekseer.Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,11 @@ void ManagerImplemented::Update(const UpdateParameter& parameter)
EndUpdate();

ExecuteSounds();

if (m_gpuTimer)
{
m_gpuTimer->UpdateResults();
}
}

void ManagerImplemented::DoUpdate(const UpdateParameter& parameter, int times)
Expand Down
2 changes: 2 additions & 0 deletions Dev/Cpp/Effekseer/Effekseer/Renderer/Effekseer.GpuTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class GpuTimer : public ReferenceObject

virtual ~GpuTimer() = default;

virtual void UpdateResults() {}

virtual void BeginStage(GpuStage stage) {}

virtual void EndStage(GpuStage stage) {}
Expand Down
2 changes: 2 additions & 0 deletions Dev/Cpp/EffekseerRendererLLGI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(PublicHeaders
set(LocalHeaders
EffekseerRendererLLGI/EffekseerRendererLLGI.Base.h
EffekseerRendererLLGI/EffekseerRendererLLGI.Base.Pre.h
EffekseerRendererLLGI/EffekseerRendererLLGI.GpuTimer.h
EffekseerRendererLLGI/EffekseerRendererLLGI.GpuParticles.h
EffekseerRendererLLGI/EffekseerRendererLLGI.MaterialLoader.h
EffekseerRendererLLGI/EffekseerRendererLLGI.ModelRenderer.h
Expand All @@ -20,6 +21,7 @@ set(LocalHeaders

set(LocalSources
EffekseerRendererLLGI/Common.cpp
EffekseerRendererLLGI/EffekseerRendererLLGI.GpuTimer.cpp
EffekseerRendererLLGI/EffekseerRendererLLGI.GpuParticles.cpp
EffekseerRendererLLGI/EffekseerRendererLLGI.MaterialLoader.cpp
EffekseerRendererLLGI/EffekseerRendererLLGI.ModelRenderer.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#include "EffekseerRendererLLGI.GpuTimer.h"

namespace EffekseerRendererLLGI
{

GpuTimer::GpuTimer(RendererImplemented* renderer, bool hasRefCount)
: m_renderer(renderer)
{
m_renderer->AddRef();
m_renderer->GetStandardRenderer()->UpdateGpuTimerCount(+1);
}

GpuTimer::~GpuTimer()
{
m_renderer->GetStandardRenderer()->UpdateGpuTimerCount(-1);
m_renderer->Release();
}

void GpuTimer::BeginStage(Effekseer::GpuStage stage)
{
assert(stage != Effekseer::GpuStage::None);

uint32_t index = static_cast<uint32_t>(stage);
assert(m_stageState[index] != State::DuringStage);

if (m_stageState[index] == State::AfterStage)
{
UpdateResults(stage);
}

m_stageState[index] = State::DuringStage;
m_currentStage = stage;
}

void GpuTimer::EndStage(Effekseer::GpuStage stage)
{
assert(stage != Effekseer::GpuStage::None);

uint32_t index = static_cast<uint32_t>(stage);
assert(m_stageState[index] == State::DuringStage);

m_stageState[index] = State::AfterStage;
m_currentStage = Effekseer::GpuStage::None;
}

void GpuTimer::UpdateResults()
{
for (uint32_t index = 1; index < 5; index++)
{
if (m_stageState[index] == State::AfterStage)
{
UpdateResults(static_cast<Effekseer::GpuStage>(index));
}
}

for (auto& [object, timeData] : m_timeData)
{
m_renderer->ResetQuery(timeData.queries.get());
}
}

void GpuTimer::UpdateResults(Effekseer::GpuStage stage)
{
auto graphicsDevice = m_renderer->GetGraphicsDevice().DownCast<EffekseerRendererLLGI::Backend::GraphicsDevice>();

assert(stage != Effekseer::GpuStage::None);
uint32_t index = static_cast<uint32_t>(stage);

for (auto& [object, timeData] : m_timeData)
{
timeData.result = 0;

uint64_t elapsedTime = 0;
for (uint32_t phase = 0; phase < NUM_PHASES; phase++)
{
if (timeData.queryedStage[phase] == stage)
{
if (timeData.queries)
{
uint64_t startTime = timeData.queries->GetQueryResult(QueryIndex(phase, TIMESTAMP_START));
uint64_t stopTime = timeData.queries->GetQueryResult(QueryIndex(phase, TIMESTAMP_STOP));
elapsedTime += graphicsDevice->GetGraphics()->TimestampToMicroseconds(stopTime - startTime);
}
timeData.queryedStage[phase] = Effekseer::GpuStage::None;
}
}
timeData.result = static_cast<int32_t>(elapsedTime);
}

m_stageState[index] = State::ResultUpdated;
}

void GpuTimer::AddTimer(const void* object)
{
assert(m_timeData.find(object) == m_timeData.end());

auto graphicsDevice = m_renderer->GetGraphicsDevice().DownCast<EffekseerRendererLLGI::Backend::GraphicsDevice>();

TimeData timeData;
timeData.queries = LLGI::CreateUniqueReference(graphicsDevice->GetGraphics()->CreateQuery(
LLGI::QueryType::Timestamp, NUM_QUERIES_PER_TIMER));

m_timeData.emplace(object, std::move(timeData));
}

void GpuTimer::RemoveTimer(const void* object)
{
auto it = m_timeData.find(object);
if (it != m_timeData.end())
{
TimeData& timeData = it->second;
m_timeData.erase(it);
}
}

void GpuTimer::Start(const void* object)
{
assert(m_currentStage != Effekseer::GpuStage::None);

auto it = m_timeData.find(object);
if (it != m_timeData.end())
{
TimeData& timeData = it->second;
for (uint32_t phase = 0; phase < NUM_PHASES; phase++)
{
if (timeData.queryedStage[phase] == Effekseer::GpuStage::None)
{
m_renderer->RecordTimestamp(timeData.queries.get(), QueryIndex(phase, TIMESTAMP_START));
timeData.queryedStage[phase] = m_currentStage;
break;
}
}
}
}

void GpuTimer::Stop(const void* object)
{
assert(m_currentStage != Effekseer::GpuStage::None);

auto it = m_timeData.find(object);
if (it != m_timeData.end())
{
TimeData& timeData = it->second;
for (uint32_t phase = 0; phase < NUM_PHASES; phase++)
{
if (timeData.queryedStage[phase] == m_currentStage)
{
m_renderer->RecordTimestamp(timeData.queries.get(), QueryIndex(phase, TIMESTAMP_STOP));
break;
}
}
}
}

int32_t GpuTimer::GetResult(const void* object)
{
auto it = m_timeData.find(object);
if (it != m_timeData.end())
{
TimeData& timeData = it->second;
return timeData.result;
}
return 0;
}

} // namespace EffekseerRendererLLGI
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

#pragma once

#include <unordered_map>
#include "GraphicsDevice.h"
#include "EffekseerRendererLLGI.RendererImplemented.h"
#include <LLGI.Query.h>

namespace EffekseerRendererLLGI
{

class GpuTimer : public ::Effekseer::GpuTimer
{
static constexpr uint32_t NUM_PHASES = 2;
static constexpr uint32_t NUM_TIMESTAMPS = 2;
static constexpr uint32_t NUM_QUERIES_PER_TIMER = NUM_PHASES * NUM_TIMESTAMPS;

static constexpr uint32_t TIMESTAMP_START = 0;
static constexpr uint32_t TIMESTAMP_STOP = 1;
static constexpr uint32_t QueryIndex(uint32_t phase, uint32_t timestamp) {
return phase * NUM_TIMESTAMPS + timestamp;
}

public:
GpuTimer(RendererImplemented* renderer, bool hasRefCount);

virtual ~GpuTimer();

void UpdateResults(Effekseer::GpuStage stage);

public: // GpuTimer
virtual void UpdateResults() override;
virtual void BeginStage(Effekseer::GpuStage stage) override;
virtual void EndStage(Effekseer::GpuStage stage) override;
virtual void AddTimer(const void* object) override;
virtual void RemoveTimer(const void* object) override;
virtual void Start(const void* object) override;
virtual void Stop(const void* object) override;
virtual int32_t GetResult(const void* object) override;

private:
RendererImplemented* m_renderer = nullptr;

struct TimeData
{
LLGI::unique_ref<LLGI::Query> queries;
Effekseer::GpuStage queryedStage[NUM_PHASES] = {};
int32_t result = 0;
};
std::unordered_map<const void*, TimeData> m_timeData;

enum class State {
NoResult,
DuringStage,
AfterStage,
ResultUpdated,
};
State m_stageState[8] = {};
Effekseer::GpuStage m_currentStage = {};
};

} // namespace EffekseerRendererLLGI
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "EffekseerRendererLLGI.ModelRenderer.h"
#include "EffekseerRendererLLGI.Shader.h"
#include "EffekseerRendererLLGI.GpuParticles.h"
#include "EffekseerRendererLLGI.GpuTimer.h"

#include <EffekseerRendererCommon/EffekseerRenderer.RibbonRendererBase.h>
#include <EffekseerRendererCommon/EffekseerRenderer.RingRendererBase.h>
Expand Down Expand Up @@ -598,6 +599,11 @@ ::Effekseer::TrackRendererRef RendererImplemented::CreateTrackRenderer()
return ::Effekseer::TrackRendererRef(new ::EffekseerRenderer::TrackRendererBase<RendererImplemented, false>(this));
}

::Effekseer::GpuTimerRef RendererImplemented::CreateGpuTimer()
{
return ::Effekseer::GpuTimerRef(new ::EffekseerRendererLLGI::GpuTimer(this, false));
}

::Effekseer::GpuParticleSystemRef RendererImplemented::CreateGpuParticleSystem(const Effekseer::GpuParticleSystem::Settings& settings)
{
auto gpuParticleSystem = ::Effekseer::GpuParticleSystemRef(new ::EffekseerRendererLLGI::GpuParticleSystem(this));
Expand Down Expand Up @@ -838,4 +844,24 @@ void RendererImplemented::ResetRenderState()
m_renderState->Update(true);
}

void RendererImplemented::ResetQuery(LLGI::Query* query)
{
GetCurrentCommandList()->ResetQuery(query);
}

void RendererImplemented::BeginQuery(LLGI::Query* query, uint32_t queryIndex)
{
GetCurrentCommandList()->BeginQuery(query, queryIndex);
}

void RendererImplemented::EndQuery(LLGI::Query* query, uint32_t queryIndex)
{
GetCurrentCommandList()->EndQuery(query, queryIndex);
}

void RendererImplemented::RecordTimestamp(LLGI::Query* query, uint32_t queryIndex)
{
GetCurrentCommandList()->RecordTimestamp(query, queryIndex);
}

} // namespace EffekseerRendererLLGI
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ class RendererImplemented : public Renderer, public ::Effekseer::ReferenceObject
@brief 軌跡レンダラーを生成する。
*/
::Effekseer::TrackRendererRef CreateTrackRenderer() override;

/**
@brief GPUタイマーを生成する。
*/
::Effekseer::GpuTimerRef CreateGpuTimer() override;

/**
@brief GPUパーティクルシステムを生成する。
Expand Down Expand Up @@ -217,6 +222,14 @@ class RendererImplemented : public Renderer, public ::Effekseer::ReferenceObject

void ResetRenderState() override;

void ResetQuery(LLGI::Query* query);

void BeginQuery(LLGI::Query* query, uint32_t queryIndex);

void EndQuery(LLGI::Query* query, uint32_t queryIndex);

void RecordTimestamp(LLGI::Query* query, uint32_t queryIndex);

virtual int GetRef() override
{
return ::Effekseer::ReferenceObject::GetRef();
Expand Down
2 changes: 1 addition & 1 deletion Dev/Editor/Effekseer/GUI/Dock/Profiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public void Update(swig.GUIManager gui, ref Texts texts)
HandleCountChart.Update(gui);
gui.Text(texts.ProfilerCpuUsage + ": " + CpuTimeChart.LatestValue + "us");
CpuTimeChart.Update(gui);
gui.Text(texts.ProfilerCpuUsage + ": " + GpuTimeChart.LatestValue + "us");
gui.Text(texts.ProfilerGpuUsage + ": " + GpuTimeChart.LatestValue + "us");
GpuTimeChart.Update(gui);
}
}
Expand Down
14 changes: 9 additions & 5 deletions Examples/CustomAsyncLoader/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ int main(int argc, char** argv)
Effekseer::Manager::UpdateParameter updateParameter;
efkManager->Update(updateParameter);

// Execute functions about DirectX
// DirectXの処理
device.ClearScreen();
// Begin to rendering pass
// 描画パスの開始
device.BeginRenderPass();

// Update a time
// 時間を更新する
Expand Down Expand Up @@ -146,8 +146,12 @@ int main(int argc, char** argv)
// エフェクトの描画終了処理を行う。
efkRenderer->EndRendering();

// Execute functions about DirectX
// DirectXの処理
// Finish to rendering pass
// 描画パスの終了
device.EndRenderPass();

// Update the display
// ディスプレイを更新
device.PresentDevice();

time++;
Expand Down
Loading

0 comments on commit 96d747a

Please sign in to comment.