xo-imgui wip
This commit is contained in:
parent
f902f93800
commit
7497751192
4 changed files with 233 additions and 26 deletions
14
default.nix
14
default.nix
|
|
@ -541,7 +541,10 @@ in
|
|||
# TODO: consider a nix project to generate this directory. nixwsl
|
||||
};
|
||||
|
||||
# like shell4 but drop etc/hostwsl2
|
||||
# like shell4 but drop etc/hostwsl2 symlink dir.
|
||||
# looks like nixpkgs mesa not built for wsl2 dxg
|
||||
# works with opengl (llvmpipe) and vulkan
|
||||
#
|
||||
shell5 = pkgs.mkShell {
|
||||
buildInputs = docutils ++ xodeps ++ devutils ++ ideutils ++ x11utils ++ gldeps ++ vkdeps ++ imguideps;
|
||||
|
||||
|
|
@ -598,18 +601,18 @@ in
|
|||
${pkgs.fontconfig}/bin/fc-cache -f
|
||||
|
||||
# works but only get glx using llvmpipe.
|
||||
# vkcube uses d3d12 however!
|
||||
# vkcube uses dzn (see VK_ICD_FILENAMES) however!
|
||||
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:${glpath}:$LD_LIBRARY_PATH
|
||||
|
||||
# need this on OSX, + claude wants it for wsl2. but looks sketchy to me
|
||||
export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
|
||||
export VK_ICD_FILENAMES="${pkgs.mesa}/share/vulkan/icd.d/dzn_icd.x86_64.json"
|
||||
|
||||
# hardware acceleration (not sure if we need this)
|
||||
# hardware acceleration (so far ineffective w/ nixpkgs mesa)
|
||||
export LIBGL_ALWAYS_SOFTWARE=0
|
||||
export MESA_LOADER_DRIVER_OVERRIDE="d3d12"
|
||||
|
||||
# wsl2-specific gpu setup (doubt this is effective)
|
||||
# wsl2-specific gpu setup (so far ineffective w/ nixpkgs mesa)
|
||||
export MESA_D3D12_DEFAULT_ADAPTER_NAME=DX
|
||||
|
||||
echo "using d3d12 vulkan driver: $VK_ICD_FILENAMES"
|
||||
|
|
@ -620,6 +623,9 @@ in
|
|||
echo "nix_libgl=${pkgs.libGL}"
|
||||
nix_libgl=${pkgs.libGL}
|
||||
|
||||
echo "nix_vk_validation: VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d"
|
||||
nix_vk_validation=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
|
||||
|
||||
# don't seem to need this -- doesn't invoke mesa hardware accel
|
||||
#echo "nix_nixgl=${pkgs.nixgl.nixGLMesa}"
|
||||
#nix_nixgl=${pkgs.nixgl.nixGLMesa}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace {
|
|||
app_duty_cycle_top(AppState * p_app_state,
|
||||
DrawState * p_draw_state)
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
scope log(XO_DEBUG(false));
|
||||
|
||||
log && log(xtag("imgui_cx", (void*)ImGui::GetCurrentContext()));
|
||||
|
||||
|
|
@ -54,6 +54,8 @@ namespace {
|
|||
* that callback captures copy details (per object!) in AppState
|
||||
*/
|
||||
if (p_app_state->gc_->enable_gc_once()) {
|
||||
scope log(XO_DEBUG(true));
|
||||
|
||||
log && log(xtag("gc-type", (p_app_state->upto_ == generation::tenured) ? "full" : "incremental"));
|
||||
|
||||
p_draw_state->state_type_ = draw_state_type::animate_gc;
|
||||
|
|
@ -83,9 +85,11 @@ namespace {
|
|||
|
||||
return [p_app_state, p_draw_state, p_f, p_counter](ImGuiContext * imgui_cx)
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
scope log(XO_DEBUG(false));
|
||||
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
app_duty_cycle_top(p_app_state, p_draw_state);
|
||||
#endif
|
||||
|
||||
log && log(xtag("imgui_cx", (void*)ImGui::GetCurrentContext()));
|
||||
|
||||
|
|
@ -94,11 +98,12 @@ namespace {
|
|||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
log && log("after NewFrame", xtag("imgui_cx", (void*)ImGui::GetCurrentContext()));
|
||||
|
||||
#ifdef NOT_WORKING
|
||||
ImGuiIO & io = ImGui::GetIO(); (void)io;
|
||||
|
||||
# ifdef NOT_WORKING
|
||||
// background
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImGui::SetNextWindowSize(io.DisplaySize);
|
||||
|
|
@ -107,24 +112,115 @@ namespace {
|
|||
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus
|
||||
| ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoDecoration);
|
||||
ImGui::End();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Create a simple ImGui window
|
||||
// 1. create a simple ImGui window
|
||||
ImGui::Begin("Hello, Vulkan + SDL2!");
|
||||
ImGui::Text("This is a minimal ImGui + Vulkan + SDL2 example!");
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
ImGui::Text("appl average %.3f ms/frame (%.1f fps)",
|
||||
1000.0f / io.Framerate, io.Framerate);
|
||||
|
||||
ImGui::Checkbox("demo window", &p_draw_state->show_demo_window_);
|
||||
ImGui::SliderFloat("float", p_f, 0.0f, 1.0f);
|
||||
if (ImGui::Button("Button"))
|
||||
++(*p_counter);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", *p_counter);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
|
||||
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
|
||||
ImGui::SliderInt("alloc/cycle", &p_app_state->alloc_per_cycle_, 1, 100);
|
||||
ImGui::SliderInt("copy animation budget", &p_draw_state->animate_copy_budget_ms_, 10, 10000);
|
||||
ImGui::NewLine();
|
||||
|
||||
/* N\u2080 = N0, N\u2081 = N1 */
|
||||
ImGui::Text("alloc [%lu] avail [%lu] ",
|
||||
p_draw_state->gcstate_.gc_allocated_,
|
||||
p_draw_state->gcstate_.gc_available_);
|
||||
|
||||
ImGui::Text("promoted [%lu] copy animation [%lu / %lu]",
|
||||
p_draw_state->gcstate_.total_promoted_,
|
||||
static_cast<std::size_t>(p_draw_state->animate_copy_hi_pct_
|
||||
* p_app_state->copy_detail_v_.size() / 100),
|
||||
p_app_state->copy_detail_v_.size());
|
||||
|
||||
ImGui::Text("mutation [%lu] mlog [%lu]",
|
||||
p_draw_state->gcstate_.total_n_mutation_,
|
||||
p_draw_state->gcstate_.gc_mlog_size_);
|
||||
|
||||
ImGui::Text("appl average %.3f ms/frame (%.1f fps)",
|
||||
1000.0f / io.Framerate, io.Framerate);
|
||||
|
||||
ImGui::Text("layout:"
|
||||
" nursery-src alloc rect [%.1f %.1f %.1f %.1f]"
|
||||
" nursery-dest alloc rect [%.1f %.1f %.1f %.1f]"
|
||||
" history rect [%.1f %.1f %.1f %.1f]",
|
||||
p_draw_state->gcw_nursery_layout_.to_alloc_rect().x_lo(),
|
||||
p_draw_state->gcw_nursery_layout_.to_alloc_rect().y_lo(),
|
||||
p_draw_state->gcw_nursery_layout_.to_alloc_rect().x_hi(),
|
||||
p_draw_state->gcw_nursery_layout_.to_alloc_rect().y_hi(),
|
||||
p_draw_state->gcw_nursery_layout_.from_alloc_rect().x_lo(),
|
||||
p_draw_state->gcw_nursery_layout_.from_alloc_rect().y_lo(),
|
||||
p_draw_state->gcw_nursery_layout_.from_alloc_rect().x_hi(),
|
||||
p_draw_state->gcw_nursery_layout_.from_alloc_rect().y_hi(),
|
||||
p_draw_state->gcw_history_rect_.x_lo(),
|
||||
p_draw_state->gcw_history_rect_.y_lo(),
|
||||
p_draw_state->gcw_history_rect_.x_hi(),
|
||||
p_draw_state->gcw_history_rect_.y_hi());
|
||||
ImGui::Text("nursery-dest copy offset [%lu] / size [%lu]"
|
||||
" tenured-dest copy offset [%lu] / size [%lu]",
|
||||
p_app_state->copy_detail_max_nursery_dest_offset_,
|
||||
p_app_state->copy_detail_nursery_dest_size_,
|
||||
p_app_state->copy_detail_max_tenured_dest_offset_,
|
||||
p_app_state->copy_detail_tenured_dest_size_);
|
||||
|
||||
ImDrawList * draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
|
||||
ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
|
||||
ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
|
||||
|
||||
/* stash so GC copy animation can find it */
|
||||
p_draw_state->gcw_draw_list_ = draw_list;
|
||||
p_draw_state->gcw_canvas_p0_ = canvas_p0;
|
||||
p_draw_state->gcw_canvas_p1_ = canvas_p1;
|
||||
|
||||
DrawState::draw_gc_state(*p_app_state,
|
||||
p_draw_state->gcstate_,
|
||||
ImRect(canvas_p0, canvas_p1),
|
||||
draw_list,
|
||||
&p_draw_state->gcw_nursery_layout_,
|
||||
&p_draw_state->gcw_tenured_layout_,
|
||||
&p_draw_state->gcw_history_rect_);
|
||||
|
||||
if (p_draw_state->state_type_ == draw_state_type::animate_gc) {
|
||||
auto animate_copy_t1 = std::chrono::steady_clock::now();
|
||||
auto animate_dt = animate_copy_t1 - p_draw_state->animate_copy_t0_;
|
||||
float animate_fraction_spent
|
||||
= (std::chrono::duration_cast<std::chrono::milliseconds>(animate_dt).count()
|
||||
/ static_cast<float>(p_draw_state->animate_copy_budget_ms_));
|
||||
|
||||
p_draw_state->animate_copy_hi_pct_ = 100.0 * animate_fraction_spent;
|
||||
|
||||
DrawState::animate_gc_copy(*p_app_state,
|
||||
*p_draw_state,
|
||||
draw_list);
|
||||
|
||||
/* see 25.0 constant in animate_gc_copy() */
|
||||
if (p_draw_state->animate_copy_hi_pct_ >= 114) {
|
||||
p_draw_state->state_type_ = draw_state_type::alloc;
|
||||
p_draw_state->animate_copy_hi_pct_ = 0;
|
||||
p_app_state->copy_detail_v_.clear();
|
||||
p_app_state->copy_detail_max_nursery_dest_offset_ = 0;
|
||||
p_app_state->copy_detail_nursery_dest_size_ = 0;
|
||||
p_app_state->copy_detail_max_tenured_dest_offset_ = 0;
|
||||
p_app_state->copy_detail_tenured_dest_size_ = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// 1. big demo window
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
// 2. big demo window
|
||||
if (p_draw_state->show_demo_window_)
|
||||
ImGui::ShowDemoWindow(&p_draw_state->show_demo_window_);
|
||||
#endif
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
|
@ -134,7 +230,7 @@ namespace {
|
|||
|
||||
void app_imgui_load_fonts(ImGuiContext * imgui_cx)
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
scope log(XO_DEBUG(false));
|
||||
log && log(xtag("imgui_cx", (void*)ImGui::GetCurrentContext()));
|
||||
|
||||
ImGuiIO & io = ImGui::GetIO(); (void)io;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@
|
|||
#include <imgui.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
//#include <SDL_vulkan.h>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
class VulkanApp {
|
||||
public:
|
||||
using ImguiDrawFn = std::function<ImDrawData * (ImGuiContext *)>;
|
||||
using time_point = std::chrono::steady_clock::time_point;
|
||||
|
||||
public:
|
||||
VulkanApp(ImguiDrawFn fn);
|
||||
|
|
@ -21,6 +23,9 @@ public:
|
|||
void assign_imgui_draw_frame(ImguiDrawFn fn);
|
||||
#endif
|
||||
|
||||
/** frames per second since inception **/
|
||||
float lifetime_fps() const;
|
||||
|
||||
/** equivalent to sequence setup(), main_loop(), cleanup() **/
|
||||
void run();
|
||||
|
||||
|
|
@ -89,6 +94,15 @@ private:
|
|||
std::vector<VkFence> in_flight_fences_;
|
||||
VkDescriptorPool descriptor_pool_;
|
||||
|
||||
/** frame counter, monotonic **/
|
||||
uint32_t n_frame_ = 0;
|
||||
/** VulkanApp start time. Captured in 1st render loop, see @ref record_command_buffer **/
|
||||
time_point start_tm_;
|
||||
/** time asof most recent render loop **/
|
||||
time_point now_tm_;
|
||||
/** time of last console report of fps **/
|
||||
time_point last_log_fps_tm_;
|
||||
|
||||
/** image index of current frame **/
|
||||
uint32_t current_frame_ = 0;
|
||||
uint32_t graphics_queue_family_ = 0;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,17 @@ VulkanApp::VulkanApp(ImguiDrawFn draw_fn)
|
|||
{
|
||||
}
|
||||
|
||||
float
|
||||
VulkanApp::lifetime_fps() const {
|
||||
if (n_frame_ > 0) {
|
||||
float elapsed_sec = 1.0e-3f * std::chrono::duration_cast<std::chrono::milliseconds>(now_tm_ - start_tm_).count();
|
||||
|
||||
return n_frame_ / elapsed_sec;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VulkanApp::setup(std::function<void (ImGuiContext *)> load_fonts) {
|
||||
if (!setup_done_) {
|
||||
|
|
@ -55,7 +66,8 @@ VulkanApp::init_window() {
|
|||
this->window_ = SDL_CreateWindow("Xo ImGui Vulkan SDL2 Frame",
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
800, 600,
|
||||
600, 600,
|
||||
//1250, 1200,
|
||||
SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if (!window_) {
|
||||
|
|
@ -83,6 +95,8 @@ VulkanApp::init_vulkan()
|
|||
void
|
||||
VulkanApp::create_instance()
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
|
||||
VkApplicationInfo appInfo{};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "ImGui Vulkan App";
|
||||
|
|
@ -128,6 +142,11 @@ VulkanApp::create_instance()
|
|||
// CRITICAL: Enable portability enumeration flag for MoltenVK
|
||||
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
|
||||
log && log(xtag("vkCreateInstance.layers", createInfo.enabledLayerCount));
|
||||
for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) {
|
||||
log && log(xtag("i", i), xtag("layer[i]", createInfo.ppEnabledLayerNames[i]));
|
||||
}
|
||||
|
||||
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create instance!");
|
||||
}
|
||||
|
|
@ -205,9 +224,27 @@ VulkanApp::create_logical_device()
|
|||
vkGetDeviceQueue(device_, graphics_queue_family_, 0, &graphics_queue_);
|
||||
}
|
||||
|
||||
const char *
|
||||
present_mode_descr(VkPresentModeKHR m) {
|
||||
switch(m) {
|
||||
case VK_PRESENT_MODE_IMMEDIATE_KHR: return "immediate";
|
||||
case VK_PRESENT_MODE_MAILBOX_KHR: return "mailbox";
|
||||
case VK_PRESENT_MODE_FIFO_KHR: return "fifo";
|
||||
case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "fifo-relaxed";
|
||||
case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: return "shared-demand-refresh";
|
||||
case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: return "shared-continuous-refresh";
|
||||
case VK_PRESENT_MODE_FIFO_LATEST_READY_EXT: return "fifo-latest-ready";
|
||||
case VK_PRESENT_MODE_MAX_ENUM_KHR: break;
|
||||
}
|
||||
|
||||
return "?present-mode";
|
||||
}
|
||||
|
||||
void
|
||||
VulkanApp::create_swapchain()
|
||||
{
|
||||
scope log(XO_DEBUG(true));
|
||||
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR
|
||||
(physical_device_, surface_, &capabilities);
|
||||
|
|
@ -234,6 +271,40 @@ VulkanApp::create_swapchain()
|
|||
imageCount = capabilities.maxImageCount;
|
||||
}
|
||||
|
||||
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
{
|
||||
uint32_t n_avail_mode = 0;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &n_avail_mode, nullptr);
|
||||
|
||||
std::vector<VkPresentModeKHR> avail_mode_v(n_avail_mode);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &n_avail_mode, avail_mode_v.data());
|
||||
|
||||
if (log) {
|
||||
log(xtag("n_avail_present_mode", n_avail_mode));
|
||||
for (uint32_t i = 0; i < n_avail_mode; ++i)
|
||||
log(xtag("i", i), xtag("avail_mode_v[i]", present_mode_descr(avail_mode_v[i])));
|
||||
}
|
||||
|
||||
std::vector<VkPresentModeKHR> prefer_mode_v = {
|
||||
VK_PRESENT_MODE_IMMEDIATE_KHR,
|
||||
VK_PRESENT_MODE_MAILBOX_KHR,
|
||||
VK_PRESENT_MODE_FIFO_KHR // forces vsync, v.slow on wsl
|
||||
};
|
||||
|
||||
bool found_flag = false;
|
||||
for (uint32_t i = 0; i < prefer_mode_v.size() && !found_flag; ++i) {
|
||||
for (uint32_t j = 0; j < avail_mode_v.size() && !found_flag; ++j) {
|
||||
if (prefer_mode_v[i] == avail_mode_v[j]) {
|
||||
present_mode = prefer_mode_v[i];
|
||||
found_flag = true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log && log(xtag("present_mode", present_mode_descr(present_mode)));
|
||||
}
|
||||
|
||||
VkSwapchainCreateInfoKHR createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
createInfo.surface = surface_;
|
||||
|
|
@ -246,7 +317,7 @@ VulkanApp::create_swapchain()
|
|||
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
createInfo.preTransform = capabilities.currentTransform;
|
||||
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
createInfo.presentMode = present_mode;
|
||||
createInfo.clipped = VK_TRUE;
|
||||
|
||||
if (vkCreateSwapchainKHR
|
||||
|
|
@ -710,15 +781,18 @@ VulkanApp::draw_frame()
|
|||
} /*draw_frame*/
|
||||
|
||||
void
|
||||
VulkanApp::record_command_buffer(VkCommandBuffer commandBuffer,
|
||||
VulkanApp::record_command_buffer(VkCommandBuffer command_buffer,
|
||||
uint32_t imageIndex)
|
||||
{
|
||||
// as long as we do this per-frame, independent of swapchain
|
||||
if (n_frame_ == 0) {
|
||||
this->start_tm_ = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
VkCommandBufferBeginInfo begin_info{};
|
||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
|
||||
if (vkBeginCommandBuffer(commandBuffer, &begin_info) != VK_SUCCESS) {
|
||||
if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to begin recording command buffer!");
|
||||
}
|
||||
|
||||
|
|
@ -733,17 +807,34 @@ VulkanApp::record_command_buffer(VkCommandBuffer commandBuffer,
|
|||
render_pass_info.clearValueCount = 1;
|
||||
render_pass_info.pClearValues = &clear_color;
|
||||
|
||||
vkCmdBeginRenderPass(commandBuffer,
|
||||
vkCmdBeginRenderPass(command_buffer,
|
||||
&render_pass_info,
|
||||
VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
ImDrawData * draw_data = this->imgui_draw_frame_(imgui_cx_);
|
||||
ImDrawData * draw_data = this->imgui_draw_frame_(imgui_cx_); (void)draw_data;
|
||||
|
||||
ImGui_ImplVulkan_RenderDrawData(draw_data, commandBuffer);
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
ImGui_ImplVulkan_RenderDrawData(draw_data, command_buffer);
|
||||
#endif
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
vkCmdEndRenderPass(command_buffer);
|
||||
|
||||
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
||||
{
|
||||
++(this->n_frame_);
|
||||
this->now_tm_ = std::chrono::steady_clock::now();
|
||||
|
||||
if ((this->n_frame_ == 1)
|
||||
|| (std::chrono::duration_cast<std::chrono::seconds>(now_tm_ - last_log_fps_tm_).count() > 1))
|
||||
{
|
||||
this->last_log_fps_tm_ = now_tm_;
|
||||
|
||||
scope log(XO_DEBUG(true));
|
||||
|
||||
log && log(xtag("lifetime_fps", this->lifetime_fps()));
|
||||
}
|
||||
}
|
||||
|
||||
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to record command buffer!");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue