mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 20:17:06 +03:00
227 lines
6.1 KiB
C++
227 lines
6.1 KiB
C++
#include "Pch.h"
|
|
#include "Viewport.h"
|
|
|
|
using namespace Flower;
|
|
using namespace Flower::UI;
|
|
|
|
const std::string VIERPORT_GViewportTileIcon = ICON_FA_CLOVER;
|
|
|
|
static AutoCVarInt32 cVarEnableStatUnit(
|
|
"stat.unit",
|
|
"Enable stat unit frame.",
|
|
"stat",
|
|
1,
|
|
CVarFlags::ReadAndWrite
|
|
);
|
|
|
|
static AutoCVarInt32 cVarEnableStatFrameGraph(
|
|
"stat.frameGraph",
|
|
"Enable stat frame graph.",
|
|
"stat",
|
|
1,
|
|
CVarFlags::ReadAndWrite
|
|
);
|
|
|
|
WidgetViewport::WidgetViewport()
|
|
: Widget(" " + VIERPORT_GViewportTileIcon + " Viewport")
|
|
{
|
|
|
|
}
|
|
|
|
WidgetViewport::~WidgetViewport() noexcept
|
|
{
|
|
|
|
}
|
|
|
|
void WidgetViewport::onInit()
|
|
{
|
|
m_renderer = GEngine->getRuntimeModule<Renderer>();
|
|
m_viewportImageSampler = RHI::SamplerManager->createSampler(SamplerFactory::pointClampBorder0000());
|
|
|
|
m_camera = std::make_unique<ViewportCamera>(this);
|
|
m_viewportRenderer = std::make_unique<DeferredRenderer>("ViewportRenderer", m_camera.get());
|
|
m_viewportRenderer->init();
|
|
|
|
m_rendererDelegate = m_renderer->rendererTickHooks.addLambda([this](const RuntimeModuleTickData& tickData, VkCommandBuffer graphicsCmd)
|
|
{
|
|
m_viewportRenderer->tick(tickData, graphicsCmd);
|
|
});
|
|
}
|
|
|
|
void WidgetViewport::onRelease()
|
|
{
|
|
m_renderer->rendererTickHooks.remove(m_rendererDelegate);
|
|
m_viewportRenderer->release();
|
|
m_viewportRenderer.reset();
|
|
}
|
|
|
|
void WidgetViewport::beforeTick()
|
|
{
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
|
}
|
|
void WidgetViewport::afterTick()
|
|
{
|
|
ImGui::PopStyleVar(1);
|
|
}
|
|
|
|
void WidgetViewport::onTick(const RuntimeModuleTickData& tickData)
|
|
{
|
|
|
|
}
|
|
|
|
void WidgetViewport::onVisibleTick(const RuntimeModuleTickData& tickData)
|
|
{
|
|
float width = glm::ceil(ImGui::GetContentRegionAvail().x);
|
|
float height = glm::ceil(ImGui::GetContentRegionAvail().y);
|
|
|
|
if (m_cacheWidth != width || m_cacheHeight != height)
|
|
{
|
|
if (!ImGui::IsMouseDragging(0))
|
|
{
|
|
m_cacheWidth = width;
|
|
m_cacheHeight = height;
|
|
m_viewportRenderer->updateRenderSize(uint32_t(width), uint32_t(height), 1.0f, 1.0f);
|
|
|
|
tryReleaseDescriptorSet(tickData.tickCount);
|
|
|
|
m_descriptorSet = ImGui_ImplVulkan_AddTexture(
|
|
m_viewportImageSampler,
|
|
m_viewportRenderer->getDisplayOutput().getView(buildBasicImageSubresource()),
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
|
);
|
|
}
|
|
}
|
|
|
|
ImVec2 startPos = ImGui::GetCursorPos();
|
|
ImGui::Image(m_descriptorSet, ImVec2(width, height));
|
|
m_bMouseInViewport = ImGui::IsItemHovered();
|
|
m_camera->tick(tickData);
|
|
|
|
|
|
ImGui::SetCursorPos(startPos);
|
|
|
|
ImGui::Spacing(); ImGui::Spacing();
|
|
ImGui::Spacing(); ImGui::Spacing();
|
|
ImGui::Indent(2.0f);
|
|
if(cVarEnableStatUnit.get() > 0)
|
|
{
|
|
const std::vector<TimeStamp>& timeStamps = m_viewportRenderer->getTimingValues();
|
|
const bool bTimeStampsAvailable = timeStamps.size() > 0;
|
|
if (bTimeStampsAvailable)
|
|
{
|
|
m_profileViewer.RECENT_HIGHEST_FRAME_TIME = 0;
|
|
|
|
m_profileViewer.FRAME_TIME_ARRAY[m_profileViewer.NUM_FRAMES - 1] = timeStamps.back().microseconds;
|
|
for (uint32_t i = 0; i < m_profileViewer.NUM_FRAMES - 1; i++)
|
|
{
|
|
m_profileViewer.FRAME_TIME_ARRAY[i] = m_profileViewer.FRAME_TIME_ARRAY[i + 1];
|
|
}
|
|
m_profileViewer.RECENT_HIGHEST_FRAME_TIME =
|
|
std::max(m_profileViewer.RECENT_HIGHEST_FRAME_TIME, m_profileViewer.FRAME_TIME_ARRAY[m_profileViewer.NUM_FRAMES - 1]);
|
|
}
|
|
const float& frameTime_us = m_profileViewer.FRAME_TIME_ARRAY[m_profileViewer.NUM_FRAMES - 1];
|
|
const float frameTime_ms = frameTime_us * 0.001f;
|
|
const int fps = bTimeStampsAvailable ? static_cast<int>(1000000.0f / frameTime_us) : 0;
|
|
static const char* textFormat = "%s : %.2f %s";
|
|
|
|
auto profileUI = [&]()
|
|
{
|
|
ImGui::BeginGroupPanel("Profiler");
|
|
{
|
|
ImGui::Text("Resolution : %ix%i", (int32_t)width, (int32_t)height);
|
|
ImGui::Text("FPS : %d (%.2f ms)", fps, frameTime_ms);
|
|
|
|
for (uint32_t i = 0; i < timeStamps.size(); i++)
|
|
{
|
|
float value = m_profileViewer.bShowMilliseconds ? timeStamps[i].microseconds / 1000.0f : timeStamps[i].microseconds;
|
|
const char* pStrUnit = m_profileViewer.bShowMilliseconds ? "ms" : "us";
|
|
ImGui::Text(textFormat, timeStamps[i].label.c_str(), value, pStrUnit);
|
|
}
|
|
}
|
|
ImGui::Spacing();
|
|
ImGui::EndGroupPanel();
|
|
};
|
|
|
|
const auto srcPos = ImGui::GetCursorPos();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.0f);
|
|
ImGui::BeginDisabled();
|
|
profileUI();
|
|
ImGui::EndDisabled();
|
|
ImGui::PopStyleVar();
|
|
ImGui::GetWindowDrawList()->AddRectFilled(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(0, 0, 0, 139), 2.0f);
|
|
|
|
ImGui::SetCursorPos(srcPos);
|
|
profileUI();
|
|
|
|
}
|
|
|
|
if (cVarEnableStatFrameGraph.get() > 0)
|
|
{
|
|
size_t iFrameTimeGraphMaxValue = 0;
|
|
size_t iFrameTimeGraphMinValue = 0;
|
|
for (int i = 0; i < m_profileViewer.countNum; ++i)
|
|
{
|
|
if (m_profileViewer.RECENT_HIGHEST_FRAME_TIME < m_profileViewer.FRAME_TIME_GRAPH_MAX_VALUES[i])
|
|
{
|
|
iFrameTimeGraphMaxValue = std::min(int(m_profileViewer.countNum - 1), i + 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
auto frameGraphView = [&]()
|
|
{
|
|
ImGui::BeginGroupPanel("GPU frame time (us)");
|
|
{
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, { 0,0,0,0 });
|
|
ImGui::PlotLines("",
|
|
m_profileViewer.FRAME_TIME_ARRAY,
|
|
m_profileViewer.NUM_FRAMES,
|
|
0,
|
|
0,
|
|
0.0f,
|
|
m_profileViewer.FRAME_TIME_GRAPH_MAX_VALUES[iFrameTimeGraphMaxValue],
|
|
ImVec2(200, 80));
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleVar();
|
|
}
|
|
ImGui::EndGroupPanel();
|
|
};
|
|
|
|
|
|
const auto srcPos = ImGui::GetCursorPos();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.0f);
|
|
ImGui::BeginDisabled();
|
|
frameGraphView();
|
|
ImGui::EndDisabled();
|
|
ImGui::PopStyleVar();
|
|
ImGui::GetWindowDrawList()->AddRectFilled(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(0, 0, 0, 139), 2.0f);
|
|
ImGui::SetCursorPos(srcPos);
|
|
frameGraphView();
|
|
}
|
|
|
|
ImGui::Unindent();
|
|
}
|
|
|
|
void WidgetViewport::tryReleaseDescriptorSet(uint64_t tickTime)
|
|
{
|
|
if (m_descriptorSet != VK_NULL_HANDLE)
|
|
{
|
|
m_lazyDestroy.push_back({ tickTime, m_descriptorSet });
|
|
m_descriptorSet = VK_NULL_HANDLE;
|
|
}
|
|
|
|
auto it = m_lazyDestroy.begin();
|
|
while (it != m_lazyDestroy.end())
|
|
{
|
|
if (it->tickTime + RHI::GMaxSwapchainCount < tickTime)
|
|
{
|
|
ImGui_ImplVulkan_FreeTextureSet(&it->set);
|
|
it = m_lazyDestroy.erase(it);
|
|
}
|
|
else
|
|
{
|
|
++it;
|
|
}
|
|
}
|
|
} |