diff --git a/flake.nix b/flake.nix index 2284b99..e0f63ca 100644 --- a/flake.nix +++ b/flake.nix @@ -28,6 +28,9 @@ } )); in { + packages = forAllSystems (pkgs: { + sim = import ./sim/package.nix pkgs; + }); devShells = forAllSystems (pkgs: { default = pkgs.mkShell { packages = with pkgs; [ diff --git a/sim/CMakeLists.txt b/sim/CMakeLists.txt index f02b352..1292ca8 100644 --- a/sim/CMakeLists.txt +++ b/sim/CMakeLists.txt @@ -7,7 +7,6 @@ project(groovylight-sim) set(CMAKE_CXX_STANDARD 20) set(CMAKE_C_STANDARD 11) - FetchContent_Declare( dear_imgui GIT_REPOSITORY https://github.com/ocornut/imgui.git @@ -24,41 +23,72 @@ FetchContent_Declare( BUILD_COMMAND "" ) - FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG v3.4.0 # or a later release ) - - FetchContent_MakeAvailable(sokol dear_imgui Catch2) +# imgui +add_library(imgui INTERFACE) +target_sources(imgui INTERFACE + ${dear_imgui_SOURCE_DIR}/imgui.cpp + ${dear_imgui_SOURCE_DIR}/imgui_draw.cpp + ${dear_imgui_SOURCE_DIR}/imgui_tables.cpp + ${dear_imgui_SOURCE_DIR}/imgui_widgets.cpp + ${dear_imgui_SOURCE_DIR}/imgui_widgets.cpp + ${dear_imgui_SOURCE_DIR}/imgui_demo.cpp +) +target_include_directories(imgui INTERFACE + ${dear_imgui_SOURCE_DIR} + ${dear_imgui_SOURCE_DIR}/backends/ +) +# target_compile_options(imgui PRIVATE -Wno-unused-but-set-variable -Wno-type-limits -Wno-missing-field-initializers) + # sokol add_library(sokol INTERFACE) target_include_directories(sokol INTERFACE ${sokol_SOURCE_DIR}) + +# Catch2 setup list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) # needed for the catch_discover_tests function + +# Verilator list(APPEND VSOURCES ../verilog/hub75e.sv ../verilog/lineram.v) set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) find_package(verilator HINTS $ENV{VERILATOR_ROOT}) + + +# OpenGL +find_package(OpenGL REQUIRED) +find_package(X11 REQUIRED) + +# SIM add_executable(sim) target_sources(sim PRIVATE src/main.cpp + src/sokol.cpp ) target_include_directories(sim PRIVATE inc/) +target_compile_options(sim PRIVATE -DSOKOL_GLCORE33) verilate(sim SOURCES ${VSOURCES} TRACE VERILATOR_ARGS -Wno-MULTITOP) -target_link_libraries(sim PRIVATE sokol) +target_link_libraries(sim PUBLIC OpenGL::GL X11 Xi Xcursor dl pthread m) +target_link_libraries(sim PUBLIC sokol) +target_link_libraries(sim PUBLIC imgui) + + +# SIM TEST add_executable(sim_test) target_sources(sim_test PRIVATE test/hub75.cpp diff --git a/sim/package.nix b/sim/package.nix new file mode 100644 index 0000000..48c7036 --- /dev/null +++ b/sim/package.nix @@ -0,0 +1,10 @@ +{ pkgs }: +stdenv.mkDerivation { + pname = "groovysim"; + version = "0.0.1"; + meta = with pkgs.lib; { + description = "Hub75 display simulator"; + }; + src = ./.; + nativeBuildInputs = with pkgs; [ cmake ]; +} diff --git a/sim/src/main.cpp b/sim/src/main.cpp index 651d285..ad27b43 100644 --- a/sim/src/main.cpp +++ b/sim/src/main.cpp @@ -1,4 +1,97 @@ +#include "sokol_app.h" +#include "sokol_gfx.h" +#include "sokol_log.h" +#include "sokol_glue.h" +#include "imgui.h" +#include "util/sokol_imgui.h" -int main() { +static bool show_test_window = true; +static bool show_another_window = false; + +static sg_pass_action pass_action; + +void init(void) { + // setup sokol-gfx, sokol-time and sokol-imgui + sg_desc desc = { }; + desc.environment = sglue_environment(); + desc.logger.func = slog_func; + sg_setup(&desc); + + // use sokol-imgui with all default-options (we're not doing + // multi-sampled rendering or using non-default pixel formats) + simgui_desc_t simgui_desc = { }; + simgui_desc.logger.func = slog_func; + simgui_setup(&simgui_desc); + + // initial clear color + pass_action.colors[0].load_action = SG_LOADACTION_CLEAR; + pass_action.colors[0].clear_value = { 0.0f, 0.5f, 0.7f, 1.0f }; +} + +void frame(void) { + const int width = sapp_width(); + const int height = sapp_height(); + simgui_new_frame({ width, height, sapp_frame_duration(), sapp_dpi_scale() }); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", &pass_action.colors[0].clear_value.r); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + ImGui::Text("w: %d, h: %d, dpi_scale: %.1f", sapp_width(), sapp_height(), sapp_dpi_scale()); + if (ImGui::Button(sapp_is_fullscreen() ? "Switch to windowed" : "Switch to fullscreen")) { + sapp_toggle_fullscreen(); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowDemoWindow() + if (show_test_window) { + ImGui::SetNextWindowPos(ImVec2(460, 20), ImGuiCond_FirstUseEver); + ImGui::ShowDemoWindow(); + } + + // the sokol_gfx draw pass + sg_pass pass = {}; + pass.action = pass_action; + pass.swapchain = sglue_swapchain(); + sg_begin_pass(&pass); + simgui_render(); + sg_end_pass(); + sg_commit(); +} + +void cleanup(void) { + simgui_shutdown(); + sg_shutdown(); +} + +void input(const sapp_event* event) { + simgui_handle_event(event); +} + +sapp_desc sokol_main(int argc, char* argv[]) { + (void)argc; (void)argv; + sapp_desc desc = { }; + desc.init_cb = init; + desc.frame_cb = frame; + desc.cleanup_cb = cleanup; + desc.event_cb = input; + desc.window_title = "Dear ImGui (sokol-app)"; + desc.ios_keyboard_resizes_canvas = false; + desc.icon.sokol_default = true; + desc.enable_clipboard = true; + desc.logger.func = slog_func; + return desc; } diff --git a/sim/src/sokol.cpp b/sim/src/sokol.cpp new file mode 100644 index 0000000..d494c44 --- /dev/null +++ b/sim/src/sokol.cpp @@ -0,0 +1,8 @@ +#define SOKOL_IMPL +#define SOKOL_IMGUI_IMPL +#include "sokol_app.h" +#include "sokol_gfx.h" +#include "sokol_log.h" +#include "sokol_glue.h" +#include "imgui.h" +#include "util/sokol_imgui.h"