Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support GpuTimer for LLGI #1008

Merged
merged 1 commit into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading