Skip to content

Commit 3883043

Browse files
committed
stop constantly reallocating memory on loader thread, wait on the gpu a lot less, fix unicode support
1 parent 7557aaf commit 3883043

File tree

5 files changed

+86
-40
lines changed

5 files changed

+86
-40
lines changed

Chikara/Main.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
Renderer r;
1919
Midi* midi;
20-
Utils u;
2120

2221
Vertex instanced_quad[] {
2322
{ {0,1}, {0,1} },
@@ -41,9 +40,10 @@ void Main::run(int argc, wchar_t** argv)
4140
auto config_path = Config::GetConfigPath();
4241
Config::GetConfig().Load(config_path);
4342
KDMAPI::Init();
44-
std::cout << "Loading " << u.GetFileName(argv[1]) << std::endl;
43+
SetConsoleOutputCP(65001);
44+
fmt::print("Loading {}\n", Utils::wstringToUtf8(Utils::GetFileName(argv[1])));
4545
std::cout << "RPC Enabled: " << Config::GetConfig().discord_rpc << std::endl;
46-
if(Config::GetConfig().discord_rpc) u.InitDiscord();
46+
if(Config::GetConfig().discord_rpc) Utils::InitDiscord();
4747
midi = new Midi(argv[1]);
4848
r.note_event_buffer = midi->note_event_buffer;
4949
r.midi_renderer_time = &midi->renderer_time;
@@ -66,7 +66,8 @@ void Main::initWindow(wchar_t** argv)
6666
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); //Set the glfw api to GLFW_NO_API because we are using Vulkan
6767
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); //Change the ability to resize the window
6868
//glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); //Window Transparancy
69-
r.window = glfwCreateWindow(default_width, default_height, std::string("Chikara | " + u.GetFileName(argv[1])).c_str(), nullptr, nullptr); //Now we create the window
69+
auto filename = Utils::wstringToUtf8(Utils::GetFileName(argv[1]));
70+
r.window = glfwCreateWindow(default_width, default_height, std::string("Chikara | " + filename).c_str(), nullptr, nullptr); //Now we create the window
7071
glfwSetWindowUserPointer(r.window, &r);
7172
glfwSetFramebufferSizeCallback(r.window, r.framebufferResizeCallback);
7273
}
@@ -121,10 +122,14 @@ void Main::mainLoop(wchar_t** argv)
121122
long long start = (std::chrono::system_clock::now().time_since_epoch() + std::chrono::seconds(1)) / std::chrono::milliseconds(1);
122123
long long end_time = (std::chrono::system_clock::now().time_since_epoch() + std::chrono::seconds(1) + std::chrono::seconds((long long)midi->song_len)) / std::chrono::milliseconds(1);
123124
midi->SpawnPlaybackThread(start_time);
125+
/*
124126
char buffer[256];
125127
sprintf(buffer, "Note Count: %s", fmt::format(std::locale("en_US.UTF-8"), "{:n}", midi->note_count));
126-
if(Config::GetConfig().discord_rpc)
127-
u.UpdatePresence(buffer, "Playing: ", u.GetFileName(argv[1]), (uint64_t)start, (uint64_t)end_time);
128+
*/
129+
if (Config::GetConfig().discord_rpc) {
130+
auto rpc_text = fmt::format(std::locale("en_US.UTF-8"), "Note Count: {:n}", midi->note_count);
131+
Utils::UpdatePresence(rpc_text.c_str(), "Playing: ", Utils::wstringToUtf8(Utils::GetFileName(argv[1])), (uint64_t)start, (uint64_t)end_time);
132+
}
128133
while(!glfwWindowShouldClose(r.window))
129134
{
130135
r.pre_time = Config::GetConfig().note_speed;
@@ -264,7 +269,7 @@ void Main::cleanup()
264269
glfwDestroyWindow(r.window);
265270

266271
glfwTerminate(); //Now we terminate
267-
u.destroyDiscord();
272+
Utils::DestroyDiscord();
268273
}
269274

270275
#pragma endregion

Chikara/Midi.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ void Midi::LoaderThread()
287287
double seconds = -1;
288288
uint64_t time = 0;
289289
bool all_ended = false;
290+
bool* tracks_ended = new bool[track_count];
290291
while (true) {
291-
bool* tracks_ended = new bool[track_count];
292292
memset(tracks_ended, 0, track_count);
293293
while (seconds < renderer_time.load() + 10.0f)
294294
{
@@ -333,10 +333,10 @@ void Midi::LoaderThread()
333333
if (all_ended)
334334
break;
335335
}
336-
delete[] tracks_ended;
337336
if (all_ended)
338337
break;
339338
}
339+
delete[] tracks_ended;
340340
misc_events.enqueue({ static_cast<float>(seconds), PLAYBACK_TERMINATE_EVENT });
341341
printf("\nloader thread exiting\n");
342342
}

Chikara/Renderer.cpp

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,27 +1487,6 @@ void Renderer::drawFrame(float time)
14871487
//vkWaitForFences(device, 1, &in_flight_fences[current_frame], VK_TRUE, UINT64_MAX);
14881488
//vkResetFences(device, 1, &in_flight_fences[current_frame]);
14891489

1490-
uint32_t img_index;
1491-
VkResult result = vkAcquireNextImageKHR(device, swap_chain, UINT64_MAX, img_available_semaphore[current_frame], VK_NULL_HANDLE, &img_index);
1492-
1493-
if(result == VK_ERROR_OUT_OF_DATE_KHR)
1494-
{
1495-
m.recreateSwapChain();
1496-
return;
1497-
} else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
1498-
throw std::runtime_error("VKERR: Failed to acquire swap chain image!");
1499-
}
1500-
1501-
//Check if a previous frame is using this image (i.e. there is its fence to wait on)
1502-
if(imgs_in_flight[img_index] != VK_NULL_HANDLE)
1503-
vkWaitForFences(device, 1, &imgs_in_flight[img_index], VK_TRUE, UINT64_MAX);
1504-
1505-
//Mark the image as now being in use by this frame
1506-
imgs_in_flight[img_index] = imgs_in_flight[current_frame];
1507-
1508-
//Update the Uniform Buffer
1509-
updateUniformBuffer(img_index, time);
1510-
15111490
size_t key_indices[256] = {};
15121491
size_t cur_offset = 0;
15131492
// yep, this iterates over the keys twice...
@@ -1590,10 +1569,35 @@ void Renderer::drawFrame(float time)
15901569
else {
15911570
last_notes_shown_count = notes_shown_size;
15921571
}
1572+
1573+
uint32_t img_index;
1574+
VkResult result = vkAcquireNextImageKHR(device, swap_chain, UINT64_MAX, img_available_semaphore[current_frame], VK_NULL_HANDLE, &img_index);
1575+
1576+
if (result == VK_ERROR_OUT_OF_DATE_KHR)
1577+
{
1578+
m.recreateSwapChain();
1579+
return;
1580+
}
1581+
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
1582+
throw std::runtime_error("VKERR: Failed to acquire swap chain image!");
1583+
}
1584+
1585+
//Check if a previous frame is using this image (i.e. there is its fence to wait on)
1586+
if (imgs_in_flight[img_index] != VK_NULL_HANDLE)
1587+
vkWaitForFences(device, 1, &imgs_in_flight[img_index], VK_TRUE, UINT64_MAX);
1588+
1589+
//Mark the image as now being in use by this frame
1590+
imgs_in_flight[img_index] = imgs_in_flight[current_frame];
1591+
1592+
//Update the Uniform Buffer
1593+
updateUniformBuffer(img_index, time);
1594+
1595+
vkWaitForFences(device, 1, &in_flight_fences[current_frame], VK_TRUE, UINT64_MAX);
15931596

1597+
VkCommandBuffer last_note_cmdbuf = nullptr; // used to submit a single note draw command buffer at the same time as the imgui one
15941598
size_t instances_left = notes_shown_size;
15951599
if (notes_shown_size == 0)
1596-
submitSingleCommandBuffer(cmd_buffers[img_index * MAX_NOTES_MULT]);
1600+
last_note_cmdbuf = cmd_buffers[img_index * MAX_NOTES_MULT];
15971601
for (size_t i = 0; i < notes_shown_size; i += MAX_NOTES) {
15981602
size_t instances_processed = min(instances_left, MAX_NOTES);
15991603
vkMapMemory(device, note_instance_buffer_mem, 0, sizeof(InstanceData) * instances_processed, 0, &data);
@@ -1611,12 +1615,17 @@ void Renderer::drawFrame(float time)
16111615
}
16121616
}
16131617

1614-
submitSingleCommandBuffer(cmd_buffers[(i == 0 ? 0 : swap_chain_framebuffers.size() * MAX_NOTES_MULT) + note_cmd_buf + img_index * MAX_NOTES_MULT]);
16151618
instances_left -= instances_processed;
16161619
last_instances_processed = instances_processed;
1620+
auto cmd_buf = cmd_buffers[(i == 0 ? 0 : swap_chain_framebuffers.size() * MAX_NOTES_MULT) + note_cmd_buf + img_index * MAX_NOTES_MULT];
1621+
if (instances_left == 0)
1622+
last_note_cmdbuf = cmd_buf;
1623+
else
1624+
submitSingleCommandBuffer(cmd_buf);
16171625
}
16181626

16191627
// render imgui command buffers
1628+
// TODO: this can be done at the same time as the above block, but how can that be done efficiently?
16201629
ImGui_ImplVulkan_NewFrame();
16211630
ImGui_ImplGlfw_NewFrame();
16221631
ImGui::NewFrame();
@@ -1650,13 +1659,38 @@ void Renderer::drawFrame(float time)
16501659
}
16511660
}
16521661

1653-
submitSingleCommandBuffer(imgui_cmd_buffers[img_index]);
1662+
//Submit to the command buffer
1663+
VkSubmitInfo submit_info = {};
1664+
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1665+
1666+
std::array<VkCommandBuffer, 2> command_buffers = { last_note_cmdbuf, imgui_cmd_buffers[img_index] };
1667+
1668+
VkSemaphore wait_semaphores[] = { img_available_semaphore[current_frame] }; //The semaphores we are waiting for
1669+
VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; //Wait with writing colors until the image is available
1670+
submit_info.waitSemaphoreCount = 1;
1671+
submit_info.pWaitSemaphores = wait_semaphores;
1672+
submit_info.pWaitDstStageMask = wait_stages;
1673+
submit_info.commandBufferCount = static_cast<uint32_t>(command_buffers.size());
1674+
submit_info.pCommandBuffers = command_buffers.data();
1675+
1676+
submit_info.signalSemaphoreCount = 1;
1677+
submit_info.pSignalSemaphores = &render_fin_semaphore[current_frame];
1678+
1679+
//vkWaitForFences(device, 1, &in_flight_fences[current_frame], VK_TRUE, UINT64_MAX);
1680+
vkResetFences(device, 1, &in_flight_fences[current_frame]);
1681+
1682+
auto submit_res = vkQueueSubmit(graphics_queue, 1, &submit_info, in_flight_fences[current_frame]);
1683+
if (submit_res != VK_SUCCESS)
1684+
{
1685+
printf("%d\n", submit_res);
1686+
throw std::runtime_error("VKERR: Failed to submit draw to command buffer!");
1687+
}
16541688

16551689
//Presentation
16561690
VkPresentInfoKHR present_info = {};
16571691
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
16581692
present_info.waitSemaphoreCount = 1;
1659-
present_info.pWaitSemaphores = &img_available_semaphore[current_frame];
1693+
present_info.pWaitSemaphores = &render_fin_semaphore[current_frame];
16601694

16611695
VkSwapchainKHR swap_chains[] = { swap_chain }; //An array of all our swap chains
16621696
present_info.swapchainCount = 1;

Chikara/Utils.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#include "Utils.h"
22

3-
std::string Utils::GetFileName(std::filesystem::path file_path)
3+
std::wstring Utils::GetFileName(std::filesystem::path file_path)
44
{
5-
return std::filesystem::path(file_path).filename().string();
5+
return std::filesystem::path(file_path).filename().wstring();
66
}
77

88
static void handleDiscordReady(const DiscordUser* connectedUser)
@@ -48,7 +48,12 @@ void Utils::UpdatePresence(const char* state, const char* details, std::string f
4848
Discord_UpdatePresence(&discordPresence);
4949
}
5050

51-
void Utils::destroyDiscord()
51+
void Utils::DestroyDiscord()
5252
{
5353
Discord_Shutdown();
5454
}
55+
56+
std::string Utils::wstringToUtf8(std::wstring str) {
57+
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
58+
return conv.to_bytes(str);
59+
}

Chikara/Utils.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
#include <iostream>
44
#include <filesystem>
5+
#include <codecvt>
56
#include <discord_rpc.h>
67

78
class Utils
89
{
910
public:
10-
std::string GetFileName(std::filesystem::path file_path);
11-
void InitDiscord();
11+
static std::wstring GetFileName(std::filesystem::path file_path);
12+
static void InitDiscord();
1213
static void UpdatePresence(const char* state, const char* details, std::string file_name, uint64_t start_time, uint64_t end_time);
13-
void destroyDiscord();
14+
static void DestroyDiscord();
15+
static std::string wstringToUtf8(std::wstring str);
1416
};
1517

0 commit comments

Comments
 (0)