diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b0fbd59..34a9e01 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,6 +47,13 @@ jobs: - name: Verify run: file ~/builds/theseus/desktop/theseus + - name: Upload macOS build + uses: actions/upload-artifact@v4 + with: + name: theseus-macos + path: ~/builds/theseus/desktop/ + if-no-files-found: error + desktop-linux: name: Desktop / Linux runs-on: ubuntu-latest @@ -79,6 +86,13 @@ jobs: - name: Verify run: file ~/builds/theseus/desktop/theseus + - name: Upload Linux build + uses: actions/upload-artifact@v4 + with: + name: theseus-linux-x64 + path: ~/builds/theseus/desktop/ + if-no-files-found: error + desktop-linux-arm64: name: Desktop / Linux ARM64 runs-on: ubuntu-24.04-arm @@ -127,6 +141,13 @@ jobs: - name: Verify run: file ~/builds/theseus/desktop/theseus + - name: Upload Linux ARM64 build + uses: actions/upload-artifact@v4 + with: + name: theseus-linux-arm64 + path: ~/builds/theseus/desktop/ + if-no-files-found: error + # Windows binaries cross-compiled from Ubuntu via mingw-w64. # SDL2/SDL2_mixer/libcurl mingw devel are pulled from upstream tarballs; # libmpv comes from shinchiro's mpv-winbuild-cmake nightly archive @@ -215,3 +236,22 @@ jobs: - name: Verify run: file ~/builds/theseus/desktop-win64/theseus.exe + + - name: Stage drop dir + # Strip the *.o / *.d compile cruft + intermediate subdirs so + # the artifact is just the runnable distro. + run: | + DROP=$HOME/builds/theseus-win64-drop + mkdir -p "$DROP" + cp -R ~/builds/theseus/desktop-win64/. "$DROP/" + find "$DROP" -name '*.o' -delete + find "$DROP" -name '*.d' -delete + rm -rf "$DROP/desktop" "$DROP/shared" "$DROP/engine" "$DROP/render" "$DROP/xbox" || true + ls -la "$DROP" + + - name: Upload Win64 build + uses: actions/upload-artifact@v4 + with: + name: theseus-windows-x64 + path: ~/builds/theseus-win64-drop/ + if-no-files-found: error diff --git a/Data/shaders/essl/fs_blit.bin b/Data/shaders/essl/fs_blit.bin new file mode 100644 index 0000000..4dec297 Binary files /dev/null and b/Data/shaders/essl/fs_blit.bin differ diff --git a/Data/shaders/essl/fs_crt.bin b/Data/shaders/essl/fs_crt.bin new file mode 100644 index 0000000..322e019 Binary files /dev/null and b/Data/shaders/essl/fs_crt.bin differ diff --git a/Data/shaders/essl/fs_ff.bin b/Data/shaders/essl/fs_ff.bin new file mode 100644 index 0000000..deea06c Binary files /dev/null and b/Data/shaders/essl/fs_ff.bin differ diff --git a/Data/shaders/essl/fs_imgui.bin b/Data/shaders/essl/fs_imgui.bin new file mode 100644 index 0000000..86b353e Binary files /dev/null and b/Data/shaders/essl/fs_imgui.bin differ diff --git a/Data/shaders/essl/fs_simple.bin b/Data/shaders/essl/fs_simple.bin new file mode 100644 index 0000000..f73868c Binary files /dev/null and b/Data/shaders/essl/fs_simple.bin differ diff --git a/Data/shaders/essl/vs_blit.bin b/Data/shaders/essl/vs_blit.bin new file mode 100644 index 0000000..3024a92 Binary files /dev/null and b/Data/shaders/essl/vs_blit.bin differ diff --git a/Data/shaders/essl/vs_ff.bin b/Data/shaders/essl/vs_ff.bin new file mode 100644 index 0000000..ebc5a44 Binary files /dev/null and b/Data/shaders/essl/vs_ff.bin differ diff --git a/Data/shaders/essl/vs_imgui.bin b/Data/shaders/essl/vs_imgui.bin new file mode 100644 index 0000000..ba42bc9 Binary files /dev/null and b/Data/shaders/essl/vs_imgui.bin differ diff --git a/Data/shaders/essl/vs_simple.bin b/Data/shaders/essl/vs_simple.bin new file mode 100644 index 0000000..fa69dc0 Binary files /dev/null and b/Data/shaders/essl/vs_simple.bin differ diff --git a/Data/shaders/glsl/fs_blit.bin b/Data/shaders/glsl/fs_blit.bin new file mode 100644 index 0000000..ea54bdc Binary files /dev/null and b/Data/shaders/glsl/fs_blit.bin differ diff --git a/Data/shaders/glsl/fs_crt.bin b/Data/shaders/glsl/fs_crt.bin new file mode 100644 index 0000000..34ebe08 Binary files /dev/null and b/Data/shaders/glsl/fs_crt.bin differ diff --git a/Data/shaders/glsl/fs_ff.bin b/Data/shaders/glsl/fs_ff.bin new file mode 100644 index 0000000..29e16b3 Binary files /dev/null and b/Data/shaders/glsl/fs_ff.bin differ diff --git a/Data/shaders/glsl/fs_imgui.bin b/Data/shaders/glsl/fs_imgui.bin new file mode 100644 index 0000000..bd43d7e Binary files /dev/null and b/Data/shaders/glsl/fs_imgui.bin differ diff --git a/Data/shaders/glsl/fs_simple.bin b/Data/shaders/glsl/fs_simple.bin new file mode 100644 index 0000000..60e2a21 Binary files /dev/null and b/Data/shaders/glsl/fs_simple.bin differ diff --git a/Data/shaders/glsl/vs_blit.bin b/Data/shaders/glsl/vs_blit.bin new file mode 100644 index 0000000..d812475 Binary files /dev/null and b/Data/shaders/glsl/vs_blit.bin differ diff --git a/Data/shaders/glsl/vs_ff.bin b/Data/shaders/glsl/vs_ff.bin new file mode 100644 index 0000000..e6c49a6 Binary files /dev/null and b/Data/shaders/glsl/vs_ff.bin differ diff --git a/Data/shaders/glsl/vs_imgui.bin b/Data/shaders/glsl/vs_imgui.bin new file mode 100644 index 0000000..8fdf298 Binary files /dev/null and b/Data/shaders/glsl/vs_imgui.bin differ diff --git a/Data/shaders/glsl/vs_simple.bin b/Data/shaders/glsl/vs_simple.bin new file mode 100644 index 0000000..a3ae9b6 Binary files /dev/null and b/Data/shaders/glsl/vs_simple.bin differ diff --git a/build/Makefile b/build/Makefile index 5303e4e..221195c 100644 --- a/build/Makefile +++ b/build/Makefile @@ -718,7 +718,7 @@ DESKTOP_OBJS = $(patsubst $(THESEUS_SRC)/%.cpp,$(DESKTOP_DIR)/%.o,$(DESKTOP_ALL_ DESKTOP_DEPS = $(DESKTOP_OBJS:.o=.d) -include $(DESKTOP_DEPS) -.PHONY: desktop desktop-clean shaders-bgfx shaders-bgfx-spirv +.PHONY: desktop desktop-clean shaders-bgfx shaders-bgfx-spirv shaders-bgfx-dx11 shaders-bgfx-glsl shaders-bgfx-essl # bgfx shader compilation (Phase 2 of project_d3d_call_audit.md). # Cross-compiles each .sc file in theseus/desktop/shaders/ to a .bin @@ -792,6 +792,70 @@ shaders-bgfx-spirv: done @echo "=== bgfx shaders compiled to $(SHADERS_OUT_DIR)/spirv/ ===" +# GLSL 1.50 (core, OpenGL 3.2+). Cross-emits cleanly from any host +# since glslang doesn't need a vendor toolchain. Runtime loader picks +# Data/shaders/glsl/ when bgfx::getRendererType() == RendererType::OpenGL. +shaders-bgfx-glsl: + @mkdir -p $(SHADERS_OUT_DIR)/glsl + @for SC in $(SHADERS_SRC_DIR)/vs_*.sc; do \ + NAME=$$(basename $$SC .sc); \ + echo "shaderc [glsl] $$NAME"; \ + $(SHADERC) -f $$SC -o $(SHADERS_OUT_DIR)/glsl/$$NAME.bin \ + --type v --platform linux --profile 150 -i $(BGFX_SHADER_INC) \ + || exit 1; \ + done + @for SC in $(SHADERS_SRC_DIR)/fs_*.sc; do \ + NAME=$$(basename $$SC .sc); \ + echo "shaderc [glsl] $$NAME"; \ + $(SHADERC) -f $$SC -o $(SHADERS_OUT_DIR)/glsl/$$NAME.bin \ + --type f --platform linux --profile 150 -i $(BGFX_SHADER_INC) \ + || exit 1; \ + done + @echo "=== bgfx shaders compiled to $(SHADERS_OUT_DIR)/glsl/ ===" + +# GLES 3.00 (OpenGL ES 3.0). Steam Deck Gaming Mode + embedded Linux. +# Cross-emits same as glsl. Runtime loader picks Data/shaders/essl/. +shaders-bgfx-essl: + @mkdir -p $(SHADERS_OUT_DIR)/essl + @for SC in $(SHADERS_SRC_DIR)/vs_*.sc; do \ + NAME=$$(basename $$SC .sc); \ + echo "shaderc [essl] $$NAME"; \ + $(SHADERC) -f $$SC -o $(SHADERS_OUT_DIR)/essl/$$NAME.bin \ + --type v --platform android --profile 300_es -i $(BGFX_SHADER_INC) \ + || exit 1; \ + done + @for SC in $(SHADERS_SRC_DIR)/fs_*.sc; do \ + NAME=$$(basename $$SC .sc); \ + echo "shaderc [essl] $$NAME"; \ + $(SHADERC) -f $$SC -o $(SHADERS_OUT_DIR)/essl/$$NAME.bin \ + --type f --platform android --profile 300_es -i $(BGFX_SHADER_INC) \ + || exit 1; \ + done + @echo "=== bgfx shaders compiled to $(SHADERS_OUT_DIR)/essl/ ===" + +# DXBC for the D3D11 renderer. Has to run on Windows because shaderc +# delegates HLSL -> DXBC compilation to fxc.exe, which only ships in +# the Windows SDK. Vertex shaders go through vs_5_0, fragment shaders +# through ps_5_0. The runtime loader picks Data/shaders/dx11/ when +# bgfx::getRendererType() == RendererType::Direct3D11. +shaders-bgfx-dx11: + @mkdir -p $(SHADERS_OUT_DIR)/dx11 + @for SC in $(SHADERS_SRC_DIR)/vs_*.sc; do \ + NAME=$$(basename $$SC .sc); \ + echo "shaderc [dx11] $$NAME"; \ + $(SHADERC) -f $$SC -o $(SHADERS_OUT_DIR)/dx11/$$NAME.bin \ + --type v --platform windows --profile s_5_0 -i $(BGFX_SHADER_INC) \ + || exit 1; \ + done + @for SC in $(SHADERS_SRC_DIR)/fs_*.sc; do \ + NAME=$$(basename $$SC .sc); \ + echo "shaderc [dx11] $$NAME"; \ + $(SHADERC) -f $$SC -o $(SHADERS_OUT_DIR)/dx11/$$NAME.bin \ + --type f --platform windows --profile s_5_0 -i $(BGFX_SHADER_INC) \ + || exit 1; \ + done + @echo "=== bgfx shaders compiled to $(SHADERS_OUT_DIR)/dx11/ ===" + desktop: $(DESKTOP_TARGET) @echo "=== desktop build complete: $(DESKTOP_TARGET) ===" diff --git a/theseus/desktop/menu_bar.cpp b/theseus/desktop/menu_bar.cpp index 4806d28..7976084 100644 --- a/theseus/desktop/menu_bar.cpp +++ b/theseus/desktop/menu_bar.cpp @@ -397,6 +397,29 @@ void RenderSettingsWindow() { SaveDesktopSettings(); } + ImGui::AlignTextToFramePadding(); ImGui::Text("Renderer:"); + ImGui::SameLine(kLabelX); ImGui::SetNextItemWidth(kWidgetW); + static const char* s_rendererLabels[] = { + "Auto", + "Direct3D 11", + "Vulkan", + "OpenGL", + "Metal", + "OpenGL ES", + }; + if (ImGui::Combo("##renderer", &g_rendererPref, s_rendererLabels, 6)) { + SaveDesktopSettings(); + } + ImGui::SameLine(); + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) + ImGui::SetTooltip( + "Takes effect on next launch.\n" + "Auto picks the best backend for your OS\n" + "(Metal on macOS, Direct3D 11 on Windows,\n" + "Vulkan on Linux). Pick a specific backend\n" + "if Auto doesn't work for you."); + ImGui::AlignTextToFramePadding(); ImGui::Text("Display Mode:"); ImGui::SameLine(kLabelX); ImGui::SetNextItemWidth(kWidgetW); if (ImGui::Combo("##dispmode", &g_windowMode, s_displayModeLabels, 3)) { diff --git a/theseus/desktop/panel_shared.h b/theseus/desktop/panel_shared.h index 03bec2c..1253d5b 100644 --- a/theseus/desktop/panel_shared.h +++ b/theseus/desktop/panel_shared.h @@ -43,6 +43,7 @@ extern int g_msaaSamples; // sdl_main.cpp extern bool g_msaaChangeRequested; extern int g_vsyncMode; // 0=adaptive, 1=on, 2=off extern bool g_vsyncChangeRequested; +extern int g_rendererPref; // 0=auto, 1=d3d11, 2=vulkan, 3=opengl (next-launch) extern int g_fpsCap; // 0=unlimited; manual frame pacing target extern bool g_hwdec; // mpv hwdec; takes effect on next media open extern int g_windowResolution; // 720 / 1080 / 1440 / 2160; 0 = native diff --git a/theseus/desktop/sdl_main.cpp b/theseus/desktop/sdl_main.cpp index 76d890f..4541939 100644 --- a/theseus/desktop/sdl_main.cpp +++ b/theseus/desktop/sdl_main.cpp @@ -481,6 +481,17 @@ void LoadDesktopSettings() { } else if (strncmp(line, "Hwdec=", 6) == 0) g_hwdec = atoi(line + 6) != 0; + else if (strncmp(line, "Renderer=", 9) == 0) { + const char* v = line + 9; + // Order matters: opengles before opengl, metal before "" prefix. + if (strncmp(v, "auto", 4) == 0) g_rendererPref = 0; + else if (strncmp(v, "d3d11", 5) == 0) g_rendererPref = 1; + else if (strncmp(v, "vulkan", 6) == 0) g_rendererPref = 2; + else if (strncmp(v, "opengles", 8) == 0 || + strncmp(v, "gles", 4) == 0) g_rendererPref = 5; + else if (strncmp(v, "opengl", 6) == 0) g_rendererPref = 3; + else if (strncmp(v, "metal", 5) == 0) g_rendererPref = 4; + } else if (strncmp(line, "Resolution=", 11) == 0) { int n = atoi(line + 11); if (n == 0 || n == 720 || n == 1080 || n == 1440 || n == 2160) @@ -540,6 +551,15 @@ void SaveDesktopSettings() { fprintf(fp, "Vsync=%d\n", g_vsyncMode); fprintf(fp, "FpsCap=%d\n", g_fpsCap); fprintf(fp, "Hwdec=%d\n", g_hwdec ? 1 : 0); + { + const char* rname = (g_rendererPref == 1) ? "d3d11" + : (g_rendererPref == 2) ? "vulkan" + : (g_rendererPref == 3) ? "opengl" + : (g_rendererPref == 4) ? "metal" + : (g_rendererPref == 5) ? "opengles" + : "auto"; + fprintf(fp, "Renderer=%s\n", rname); + } fprintf(fp, "Resolution=%d\n", g_windowResolution); fprintf(fp, "DisplayMode=%d\n", g_windowMode); fprintf(fp, "\n[CRT]\n"); @@ -794,6 +814,11 @@ int g_msaaSamples = 4; // 0=off, 2/4/8x MSAA (default 4x) bool g_msaaChangeRequested = false; // 0=adaptive (-1, fall back to 1), 1=on (1), 2=off (0). Default adaptive. int g_vsyncMode = 0; +// 0 = auto, 1 = d3d11, 2 = vulkan, 3 = opengl, 4 = metal, 5 = opengles. +// Takes effect on next launch; bgfx::init cannot switch backends mid-session. +// Picking a backend the host doesn't support (e.g. d3d11 on Linux, metal on +// Windows) falls through to bgfx auto-pick during init. +int g_rendererPref = 0; bool g_vsyncChangeRequested = false; // Manual FPS cap (0 = unlimited). Applied via SDL_Delay before SwapWindow. @@ -1189,13 +1214,19 @@ int main(int argc, char* argv[]) { bgfxInit.resolution.width = 1280; bgfxInit.resolution.height = 720; bgfxInit.resolution.reset = BgfxResetFlags(); - // macOS: auto-pick (Metal). Windows: pin Vulkan. D3D11 would work - // too but needs DXBC, which only fxc.exe (Windows-only) can build. -#if defined(_WIN32) - bgfxInit.type = bgfx::RendererType::Vulkan; -#else - bgfxInit.type = bgfx::RendererType::Count; // auto-pick best backend -#endif + // Renderer pick. User override via Config.ini Renderer key + // (auto / d3d11 / vulkan / opengl / metal / opengles). Default + // is auto, which lets bgfx pick the best backend for the host + // (Metal on macOS, D3D11 on Windows, Vulkan on Linux). Picking + // a backend the host doesnt provide drops through to auto. + switch (g_rendererPref) { + case 1: bgfxInit.type = bgfx::RendererType::Direct3D11; break; + case 2: bgfxInit.type = bgfx::RendererType::Vulkan; break; + case 3: bgfxInit.type = bgfx::RendererType::OpenGL; break; + case 4: bgfxInit.type = bgfx::RendererType::Metal; break; + case 5: bgfxInit.type = bgfx::RendererType::OpenGLES; break; + default: bgfxInit.type = bgfx::RendererType::Count; break; + } if (!bgfx::init(bgfxInit)) { fprintf(stderr, "bgfx::init failed\n"); } else {