From 4f480e1d4946c18dbe02aea889d0f2d710389b89 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Mon, 24 Aug 2026 20:54:34 +0200 Subject: [PATCH 01/60] Add bgfx dependency --- CMakeLists.txt | 6 +++++- src/config.h.in | 1 + vcpkg.json | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c02efeac..04a86a751 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1176,9 +1176,13 @@ if (NOT DEFINED IMPACTO_DISABLE_OPENGL) src/renderer/opengl/3d/renderable3d.h src/renderer/opengl/3d/scene.h ) - endif () +if (NOT DEFINED IMPACTO_DISABLE_BGFX) + find_package(bgfx CONFIG REQUIRED) + list(APPEND Impacto_Libs bgfx::bgfx) +endif() + if (NOT DEFINED IMPACTO_DISABLE_FFMPEG) list(APPEND Impacto_Src src/video/ffmpegplayer.cpp diff --git a/src/config.h.in b/src/config.h.in index 825790d24..acb41956f 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -4,6 +4,7 @@ #cmakedefine01 IMPACTO_GL_DEBUG #cmakedefine01 IMPACTO_HAVE_THREADS #cmakedefine01 IMPACTO_USE_SDL_HIGHDPI +#cmakedefine IMPACTO_DISABLE_BGFX #cmakedefine IMPACTO_DISABLE_VULKAN #cmakedefine IMPACTO_DISABLE_DX9 #cmakedefine IMPACTO_DISABLE_OPENGL diff --git a/vcpkg.json b/vcpkg.json index 6c9e5d207..64386a5fe 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -52,7 +52,8 @@ "boost-circular-buffer", "toml11", "freetype", - "harfbuzz" + "harfbuzz", + "bgfx" ], "overrides": [ { From 05324136aecdf9db316c671dd0e50bf1f4a99c1e Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Mon, 24 Aug 2026 21:23:14 +0200 Subject: [PATCH 02/60] Deprecate Vulkan and DirectX9 --- CMakeLists.txt | 59 - README.md | 2 +- src/renderer/3d/camera.cpp | 7 +- src/renderer/dx9/3d/renderable3d.cpp | 741 ------ src/renderer/dx9/3d/renderable3d.h | 92 - src/renderer/dx9/3d/scene.cpp | 81 - src/renderer/dx9/3d/scene.h | 29 - src/renderer/dx9/nv12frame.cpp | 52 - src/renderer/dx9/nv12frame.h | 30 - src/renderer/dx9/renderer.cpp | 860 ------- src/renderer/dx9/renderer.h | 179 -- src/renderer/dx9/shader.cpp | 85 - src/renderer/dx9/shader.h | 24 - src/renderer/dx9/utils.h | 13 - src/renderer/dx9/window.cpp | 84 - src/renderer/dx9/window.h | 23 - src/renderer/dx9/yuvframe.cpp | 44 - src/renderer/dx9/yuvframe.h | 30 - src/renderer/renderer.cpp | 16 - src/renderer/vulkan/3d/renderable3d.cpp | 1154 ---------- src/renderer/vulkan/3d/renderable3d.h | 109 - src/renderer/vulkan/3d/scene.cpp | 82 - src/renderer/vulkan/3d/scene.h | 32 - src/renderer/vulkan/nv12frame.cpp | 157 -- src/renderer/vulkan/nv12frame.h | 31 - src/renderer/vulkan/pipeline.cpp | 241 -- src/renderer/vulkan/pipeline.h | 38 - src/renderer/vulkan/renderer.cpp | 2033 ----------------- src/renderer/vulkan/renderer.h | 276 --- src/renderer/vulkan/utils.cpp | 97 - src/renderer/vulkan/utils.h | 69 - src/renderer/vulkan/window.cpp | 81 - src/renderer/vulkan/window.h | 23 - src/renderer/vulkan/yuvframe.cpp | 175 -- src/renderer/vulkan/yuvframe.h | 31 - src/renderer/window.cpp | 12 - src/shaders/dx9/CCMessageBoxSprite_frag.hlsl | 36 - src/shaders/dx9/CCMessageBoxSprite_vert.hlsl | 24 - src/shaders/dx9/CHLCCMenuBackground_frag.hlsl | 32 - src/shaders/dx9/CHLCCMenuBackground_vert.hlsl | 24 - src/shaders/dx9/MaskedSpriteNoAlpha_frag.hlsl | 32 - src/shaders/dx9/MaskedSpriteNoAlpha_vert.hlsl | 24 - src/shaders/dx9/MaskedSprite_frag.hlsl | 31 - src/shaders/dx9/MaskedSprite_vert.hlsl | 24 - src/shaders/dx9/NV12Frame_frag.hlsl | 37 - src/shaders/dx9/NV12Frame_vert.hlsl | 24 - .../dx9/Renderable3D_Background_frag.hlsl | 9 - .../dx9/Renderable3D_Background_vert.hlsl | 20 - .../dx9/Renderable3D_Character_frag.hlsl | 108 - .../dx9/Renderable3D_Character_vert.hlsl | 53 - src/shaders/dx9/Renderable3D_Eye_frag.hlsl | 53 - src/shaders/dx9/Renderable3D_Eye_vert.hlsl | 48 - .../dx9/Renderable3D_Outline_frag.hlsl | 52 - .../dx9/Renderable3D_Outline_vert.hlsl | 69 - src/shaders/dx9/Sprite_frag.hlsl | 12 - src/shaders/dx9/Sprite_inverted_frag.hlsl | 16 - src/shaders/dx9/Sprite_inverted_vert.hlsl | 24 - src/shaders/dx9/Sprite_vert.hlsl | 24 - src/shaders/dx9/YUVFrame_frag.hlsl | 39 - src/shaders/dx9/YUVFrame_vert.hlsl | 24 - .../vulkan/CCMessageBoxSprite_frag.glsl | 38 - .../vulkan/CCMessageBoxSprite_frag.spv | Bin 2708 -> 0 bytes .../vulkan/CCMessageBoxSprite_vert.glsl | 18 - .../vulkan/CCMessageBoxSprite_vert.spv | Bin 1364 -> 0 bytes .../vulkan/CHLCCMenuBackground_frag.glsl | 33 - .../vulkan/CHLCCMenuBackground_frag.spv | Bin 2392 -> 0 bytes .../vulkan/CHLCCMenuBackground_vert.glsl | 15 - .../vulkan/CHLCCMenuBackground_vert.spv | Bin 1216 -> 0 bytes .../vulkan/MaskedSpriteNoAlpha_frag.glsl | 35 - .../vulkan/MaskedSpriteNoAlpha_frag.spv | Bin 2708 -> 0 bytes .../vulkan/MaskedSpriteNoAlpha_vert.glsl | 18 - .../vulkan/MaskedSpriteNoAlpha_vert.spv | Bin 1364 -> 0 bytes src/shaders/vulkan/MaskedSprite_frag.glsl | 33 - src/shaders/vulkan/MaskedSprite_frag.spv | Bin 2484 -> 0 bytes src/shaders/vulkan/MaskedSprite_vert.glsl | 18 - src/shaders/vulkan/MaskedSprite_vert.spv | Bin 1364 -> 0 bytes src/shaders/vulkan/NV12Frame_frag.glsl | 38 - src/shaders/vulkan/NV12Frame_frag.spv | Bin 2572 -> 0 bytes src/shaders/vulkan/NV12Frame_vert.glsl | 16 - src/shaders/vulkan/NV12Frame_vert.spv | Bin 1164 -> 0 bytes .../vulkan/Renderable3D_Background_frag.glsl | 15 - .../vulkan/Renderable3D_Background_frag.spv | Bin 780 -> 0 bytes .../vulkan/Renderable3D_Background_vert.glsl | 21 - .../vulkan/Renderable3D_Background_vert.spv | Bin 1500 -> 0 bytes .../vulkan/Renderable3D_Character_frag.glsl | 106 - .../vulkan/Renderable3D_Character_frag.spv | Bin 7148 -> 0 bytes .../vulkan/Renderable3D_Character_vert.glsl | 52 - .../vulkan/Renderable3D_Character_vert.spv | Bin 4812 -> 0 bytes src/shaders/vulkan/Renderable3D_Eye_frag.glsl | 59 - src/shaders/vulkan/Renderable3D_Eye_frag.spv | Bin 4188 -> 0 bytes src/shaders/vulkan/Renderable3D_Eye_vert.glsl | 48 - src/shaders/vulkan/Renderable3D_Eye_vert.spv | Bin 4272 -> 0 bytes .../vulkan/Renderable3D_Outline_frag.glsl | 56 - .../vulkan/Renderable3D_Outline_frag.spv | Bin 3872 -> 0 bytes .../vulkan/Renderable3D_Outline_vert.glsl | 69 - .../vulkan/Renderable3D_Outline_vert.spv | Bin 5588 -> 0 bytes src/shaders/vulkan/Sprite_frag.glsl | 11 - src/shaders/vulkan/Sprite_frag.spv | Bin 728 -> 0 bytes src/shaders/vulkan/Sprite_inverted_frag.glsl | 15 - src/shaders/vulkan/Sprite_inverted_frag.spv | Bin 1116 -> 0 bytes src/shaders/vulkan/Sprite_inverted_vert.glsl | 16 - src/shaders/vulkan/Sprite_inverted_vert.spv | Bin 1236 -> 0 bytes src/shaders/vulkan/Sprite_vert.glsl | 16 - src/shaders/vulkan/Sprite_vert.spv | Bin 1236 -> 0 bytes src/shaders/vulkan/YUVFrame_frag.glsl | 39 - src/shaders/vulkan/YUVFrame_frag.spv | Bin 2704 -> 0 bytes src/shaders/vulkan/YUVFrame_vert.glsl | 16 - src/shaders/vulkan/YUVFrame_vert.spv | Bin 1236 -> 0 bytes src/userconfig.h | 3 +- 109 files changed, 3 insertions(+), 8732 deletions(-) delete mode 100644 src/renderer/dx9/3d/renderable3d.cpp delete mode 100644 src/renderer/dx9/3d/renderable3d.h delete mode 100644 src/renderer/dx9/3d/scene.cpp delete mode 100644 src/renderer/dx9/3d/scene.h delete mode 100644 src/renderer/dx9/nv12frame.cpp delete mode 100644 src/renderer/dx9/nv12frame.h delete mode 100644 src/renderer/dx9/renderer.cpp delete mode 100644 src/renderer/dx9/renderer.h delete mode 100644 src/renderer/dx9/shader.cpp delete mode 100644 src/renderer/dx9/shader.h delete mode 100644 src/renderer/dx9/utils.h delete mode 100644 src/renderer/dx9/window.cpp delete mode 100644 src/renderer/dx9/window.h delete mode 100644 src/renderer/dx9/yuvframe.cpp delete mode 100644 src/renderer/dx9/yuvframe.h delete mode 100644 src/renderer/vulkan/3d/renderable3d.cpp delete mode 100644 src/renderer/vulkan/3d/renderable3d.h delete mode 100644 src/renderer/vulkan/3d/scene.cpp delete mode 100644 src/renderer/vulkan/3d/scene.h delete mode 100644 src/renderer/vulkan/nv12frame.cpp delete mode 100644 src/renderer/vulkan/nv12frame.h delete mode 100644 src/renderer/vulkan/pipeline.cpp delete mode 100644 src/renderer/vulkan/pipeline.h delete mode 100644 src/renderer/vulkan/renderer.cpp delete mode 100644 src/renderer/vulkan/renderer.h delete mode 100644 src/renderer/vulkan/utils.cpp delete mode 100644 src/renderer/vulkan/utils.h delete mode 100644 src/renderer/vulkan/window.cpp delete mode 100644 src/renderer/vulkan/window.h delete mode 100644 src/renderer/vulkan/yuvframe.cpp delete mode 100644 src/renderer/vulkan/yuvframe.h delete mode 100644 src/shaders/dx9/CCMessageBoxSprite_frag.hlsl delete mode 100644 src/shaders/dx9/CCMessageBoxSprite_vert.hlsl delete mode 100644 src/shaders/dx9/CHLCCMenuBackground_frag.hlsl delete mode 100644 src/shaders/dx9/CHLCCMenuBackground_vert.hlsl delete mode 100644 src/shaders/dx9/MaskedSpriteNoAlpha_frag.hlsl delete mode 100644 src/shaders/dx9/MaskedSpriteNoAlpha_vert.hlsl delete mode 100644 src/shaders/dx9/MaskedSprite_frag.hlsl delete mode 100644 src/shaders/dx9/MaskedSprite_vert.hlsl delete mode 100644 src/shaders/dx9/NV12Frame_frag.hlsl delete mode 100644 src/shaders/dx9/NV12Frame_vert.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Background_frag.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Background_vert.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Character_frag.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Character_vert.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Eye_frag.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Eye_vert.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Outline_frag.hlsl delete mode 100644 src/shaders/dx9/Renderable3D_Outline_vert.hlsl delete mode 100644 src/shaders/dx9/Sprite_frag.hlsl delete mode 100644 src/shaders/dx9/Sprite_inverted_frag.hlsl delete mode 100644 src/shaders/dx9/Sprite_inverted_vert.hlsl delete mode 100644 src/shaders/dx9/Sprite_vert.hlsl delete mode 100644 src/shaders/dx9/YUVFrame_frag.hlsl delete mode 100644 src/shaders/dx9/YUVFrame_vert.hlsl delete mode 100644 src/shaders/vulkan/CCMessageBoxSprite_frag.glsl delete mode 100644 src/shaders/vulkan/CCMessageBoxSprite_frag.spv delete mode 100644 src/shaders/vulkan/CCMessageBoxSprite_vert.glsl delete mode 100644 src/shaders/vulkan/CCMessageBoxSprite_vert.spv delete mode 100644 src/shaders/vulkan/CHLCCMenuBackground_frag.glsl delete mode 100644 src/shaders/vulkan/CHLCCMenuBackground_frag.spv delete mode 100644 src/shaders/vulkan/CHLCCMenuBackground_vert.glsl delete mode 100644 src/shaders/vulkan/CHLCCMenuBackground_vert.spv delete mode 100644 src/shaders/vulkan/MaskedSpriteNoAlpha_frag.glsl delete mode 100644 src/shaders/vulkan/MaskedSpriteNoAlpha_frag.spv delete mode 100644 src/shaders/vulkan/MaskedSpriteNoAlpha_vert.glsl delete mode 100644 src/shaders/vulkan/MaskedSpriteNoAlpha_vert.spv delete mode 100644 src/shaders/vulkan/MaskedSprite_frag.glsl delete mode 100644 src/shaders/vulkan/MaskedSprite_frag.spv delete mode 100644 src/shaders/vulkan/MaskedSprite_vert.glsl delete mode 100644 src/shaders/vulkan/MaskedSprite_vert.spv delete mode 100644 src/shaders/vulkan/NV12Frame_frag.glsl delete mode 100644 src/shaders/vulkan/NV12Frame_frag.spv delete mode 100644 src/shaders/vulkan/NV12Frame_vert.glsl delete mode 100644 src/shaders/vulkan/NV12Frame_vert.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Background_frag.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Background_frag.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Background_vert.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Background_vert.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Character_frag.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Character_frag.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Character_vert.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Character_vert.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Eye_frag.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Eye_frag.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Eye_vert.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Eye_vert.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Outline_frag.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Outline_frag.spv delete mode 100644 src/shaders/vulkan/Renderable3D_Outline_vert.glsl delete mode 100644 src/shaders/vulkan/Renderable3D_Outline_vert.spv delete mode 100644 src/shaders/vulkan/Sprite_frag.glsl delete mode 100644 src/shaders/vulkan/Sprite_frag.spv delete mode 100644 src/shaders/vulkan/Sprite_inverted_frag.glsl delete mode 100644 src/shaders/vulkan/Sprite_inverted_frag.spv delete mode 100644 src/shaders/vulkan/Sprite_inverted_vert.glsl delete mode 100644 src/shaders/vulkan/Sprite_inverted_vert.spv delete mode 100644 src/shaders/vulkan/Sprite_vert.glsl delete mode 100644 src/shaders/vulkan/Sprite_vert.spv delete mode 100644 src/shaders/vulkan/YUVFrame_frag.glsl delete mode 100644 src/shaders/vulkan/YUVFrame_frag.spv delete mode 100644 src/shaders/vulkan/YUVFrame_vert.glsl delete mode 100644 src/shaders/vulkan/YUVFrame_vert.spv diff --git a/CMakeLists.txt b/CMakeLists.txt index 04a86a751..52de35e67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -820,8 +820,6 @@ set(Impacto_Lib_Targets ) if (NX OR EMSCRIPTEN) - set(IMPACTO_DISABLE_VULKAN ON) - set(IMPACTO_DISABLE_DX9 ON) set(IMPACTO_DISABLE_MMAP ON) set(BUILD_SHARED_LIBS OFF) endif () @@ -1229,63 +1227,6 @@ if (NOT DEFINED IMPACTO_DISABLE_MSPACK) list(APPEND Impacto_Header src/io/lzxstream.h) endif () -if (NOT DEFINED IMPACTO_DISABLE_VULKAN) - list(APPEND Impacto_Src - src/renderer/vulkan/window.cpp - src/renderer/vulkan/renderer.cpp - src/renderer/vulkan/pipeline.cpp - src/renderer/vulkan/utils.cpp - src/renderer/vulkan/yuvframe.cpp - src/renderer/vulkan/nv12frame.cpp - src/renderer/vulkan/3d/renderable3d.cpp - src/renderer/vulkan/3d/scene.cpp - ) - list(APPEND Impacto_Header - src/renderer/vulkan/window.h - src/renderer/vulkan/renderer.h - src/renderer/vulkan/pipeline.h - src/renderer/vulkan/utils.h - src/renderer/vulkan/yuvframe.h - src/renderer/vulkan/nv12frame.h - src/renderer/vulkan/3d/renderable3d.h - src/renderer/vulkan/3d/scene.h - ) - - find_package(Vulkan REQUIRED) - - list(APPEND Impacto_Libs - ${Vulkan_LIBRARIES} - ) - list(APPEND Impacto_Include_Dirs ${Vulkan_INCLUDE_DIRS}) -endif () - -if (NOT DEFINED IMPACTO_DISABLE_DX9) - list(APPEND Impacto_Src - src/renderer/dx9/renderer.cpp - src/renderer/dx9/window.cpp - src/renderer/dx9/shader.cpp - src/renderer/dx9/yuvframe.cpp - src/renderer/dx9/nv12frame.cpp - src/renderer/dx9/3d/scene.cpp - src/renderer/dx9/3d/renderable3d.cpp - ) - list(APPEND Impacto_Header - src/renderer/dx9/utils.h - src/renderer/dx9/renderer.h - src/renderer/dx9/window.h - src/renderer/dx9/shader.h - src/renderer/dx9/yuvframe.h - src/renderer/dx9/nv12frame.h - src/renderer/dx9/3d/scene.h - src/renderer/dx9/3d/renderable3d.h - ) - - list(APPEND Impacto_Libs - d3d9 - d3dcompiler - ) -endif () - configure_file(src/version.h.in ${PROJECT_BINARY_DIR}/include/version.h) if(ANDROID) diff --git a/README.md b/README.md index c1be329ba..9f8476e21 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ **impacto is in active development**. At current stage it should be possible to reach all endings in at least one supported game - "Memories Off 6 \~T-Wave\~." However, some functionality and architectural design are still missing and **no games are fully complete yet**. Refer to [#1](https://github.com/CommitteeOfZero/impacto/issues/1) for supported games and remaining work. -impacto is currently being developed for **64-bit Windows 10 and desktop Linux PCs** but we've successfully experimented on macOS, Android (ARM), Switch (homebrew and Linux) and HTML5/WebAssembly (via Emscripten) and full official Android support is planned. OpenGL is used for the graphics renderer with experimental Vulkan and DirectX 9 options available. +impacto is currently being developed for **64-bit Windows 10 and desktop Linux PCs** but we've successfully experimented on macOS, Android (ARM), Switch (homebrew and Linux) and HTML5/WebAssembly (via Emscripten) and full official Android support is planned. OpenGL is used for the graphics renderer. ## Building diff --git a/src/renderer/3d/camera.cpp b/src/renderer/3d/camera.cpp index 1b792c514..e906e740d 100644 --- a/src/renderer/3d/camera.cpp +++ b/src/renderer/3d/camera.cpp @@ -46,12 +46,7 @@ void Camera::Recalculate() { CameraTransform.Matrix()); // move the world, not the camera } - if (UserConfig::AdvancedSettings.ActiveRenderer == RendererType::Vulkan) { - Projection = glm::perspectiveRH_ZO(Fov, AspectRatio, Near, Far); - Projection[1][1] *= -1.0f; - } else { - Projection = glm::perspective(Fov, AspectRatio, Near, Far); - } + Projection = glm::perspective(Fov, AspectRatio, Near, Far); ViewProjection = Projection * View; } diff --git a/src/renderer/dx9/3d/renderable3d.cpp b/src/renderer/dx9/3d/renderable3d.cpp deleted file mode 100644 index 8c54f8314..000000000 --- a/src/renderer/dx9/3d/renderable3d.cpp +++ /dev/null @@ -1,741 +0,0 @@ -#include -#include - -#include "renderable3d.h" - -#include "../renderer.h" -#include "../../3d/camera.h" -#include "../../3d/modelanimator.h" -#include "../../../log.h" -#include "../../../profile/scene3d.h" - -namespace Impacto { -namespace DirectX9 { - -static uint32_t TextureDummy = 0; - -// character -static Shader *ShaderMain = 0, *ShaderOutline = 0, *ShaderEye = 0; - -// background -static Shader* ShaderBackground = 0; - -static glm::mat4 ViewProjection; - -static IScene3D* CurrentScene; -static Camera* CurrentCamera; - -static bool IsInit = false; - -static MaterialType CurrentMaterial = MT_None; -static bool CurrentMaterialIsDepthWrite = false; -static bool CurrentMaterialIsBackfaceCull = false; - -static DirectX9Window* Window; -static IDirect3DDevice9* Device; - -void Renderable3D::Init(DirectX9Window* window, IDirect3DDevice9* device) { - assert(IsInit == false); - ImpLog(LogLevel::Info, LogChannel::Renderable3D, - "Initializing Renderable3D system\n"); - IsInit = true; - - Window = window; - Device = device; - - IDirect3DVertexDeclaration9* modelVertexDeclaration; - D3D_SHADER_MACRO* shaderMacros = nullptr; - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - D3D_SHADER_MACRO dashMacros[] = {"IsDaSH", "1", NULL, NULL}; - shaderMacros = dashMacros; - - std::vector vertexDeclDesc{ - {0, offsetof(VertexBufferDaSH, Position), D3DDECLTYPE_FLOAT3, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, - {0, offsetof(VertexBufferDaSH, Normal), D3DDECLTYPE_FLOAT3, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, - {0, offsetof(VertexBufferDaSH, UV), D3DDECLTYPE_FLOAT2, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, - {0, offsetof(VertexBufferDaSH, BoneIndices), D3DDECLTYPE_UBYTE4, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0}, - {0, offsetof(VertexBufferDaSH, BoneWeights), D3DDECLTYPE_FLOAT4, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, - D3DDECL_END()}; - Device->CreateVertexDeclaration(vertexDeclDesc.data(), - &modelVertexDeclaration); - } else { - std::vector vertexDeclDesc{ - {0, offsetof(VertexBuffer, Position), D3DDECLTYPE_FLOAT3, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, - {0, offsetof(VertexBuffer, Normal), D3DDECLTYPE_FLOAT3, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, - {0, offsetof(VertexBuffer, UV), D3DDECLTYPE_FLOAT2, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, - {0, offsetof(VertexBuffer, BoneIndices), D3DDECLTYPE_UBYTE4, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0}, - {0, offsetof(VertexBuffer, BoneWeights), D3DDECLTYPE_FLOAT4, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, - D3DDECL_END()}; - Device->CreateVertexDeclaration(vertexDeclDesc.data(), - &modelVertexDeclaration); - } - - ShaderMain = new Shader(); - ShaderMain->Compile("Renderable3D_Character", Device, modelVertexDeclaration, - shaderMacros); - ShaderOutline = new Shader(); - ShaderOutline->Compile("Renderable3D_Outline", Device, modelVertexDeclaration, - shaderMacros); - ShaderEye = new Shader(); - ShaderEye->Compile("Renderable3D_Eye", Device, modelVertexDeclaration, - shaderMacros); - - IDirect3DVertexDeclaration9* bgVertexDeclaration; - std::vector vertexDeclDesc{ - {0, offsetof(BgVertexBuffer, Position), D3DDECLTYPE_FLOAT3, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, - {0, offsetof(BgVertexBuffer, UV), D3DDECLTYPE_FLOAT2, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, - D3DDECL_END()}; - Device->CreateVertexDeclaration(vertexDeclDesc.data(), &bgVertexDeclaration); - ShaderBackground = new Shader(); - ShaderBackground->Compile("Renderable3D_Background", Device, - bgVertexDeclaration); - - Texture texDummy; - texDummy.Load1x1(); - TextureDummy = texDummy.Submit(); -} - -void Renderable3D::BeginFrame(IScene3D* scene, Camera* camera) { - CurrentMaterial = MT_None; - - CurrentScene = scene; - CurrentCamera = camera; - /* SceneUniformBufferType entry{}; - entry.ViewProjection = camera->ViewProjection; - entry.Tint = scene->Tint; - entry.WorldLightPosition = scene->LightPosition; - entry.WorldEyePosition = camera->CameraTransform.Position; - entry.DarkMode = scene->DarkMode; - memcpy(SceneUniformBuffersMapped[CurrentFrameIndex], &entry, - sizeof(SceneUniformBufferType));*/ - - ViewProjection = camera->ViewProjection; -} - -void Renderable3D::SetSceneUniformValues() { - if (StaticModel->Type != ModelType_Background) { - SceneUniformBufferType entry{}; - entry.ViewProjection = CurrentCamera->ViewProjection; - entry.Tint = CurrentScene->Tint; - entry.WorldLightPosition = CurrentScene->LightPosition; - entry.WorldEyePosition = CurrentCamera->CameraTransform.Position; - entry.DarkMode = CurrentScene->DarkMode; - - Device->SetPixelShaderConstantF(0, glm::value_ptr(entry.ViewProjection), 4); - Device->SetPixelShaderConstantF(4, glm::value_ptr(entry.Tint), 1); - Device->SetPixelShaderConstantF(5, glm::value_ptr(entry.WorldLightPosition), - 1); - Device->SetPixelShaderConstantF(6, glm::value_ptr(entry.WorldEyePosition), - 1); - Device->SetPixelShaderConstantB(0, (BOOL*)&entry.DarkMode, 1); - - Device->SetVertexShaderConstantF(0, glm::value_ptr(entry.ViewProjection), - 4); - Device->SetVertexShaderConstantF(4, glm::value_ptr(entry.Tint), 1); - Device->SetVertexShaderConstantF( - 5, glm::value_ptr(entry.WorldLightPosition), 1); - Device->SetVertexShaderConstantF(6, glm::value_ptr(entry.WorldEyePosition), - 1); - Device->SetVertexShaderConstantB(0, (BOOL*)&entry.DarkMode, 1); - } -} - -bool Renderable3D::LoadSync(uint32_t modelId) { - assert(IsUsed == false); - - ImpLog(LogLevel::Info, LogChannel::Renderable3D, - "Creating renderable (model ID {:d})\n", modelId); - - StaticModel = Model::Load(modelId); - ModelTransform = Transform(); - PrevPoseWeight = 0.0f; - - if (!StaticModel) { - ImpLog(LogLevel::Error, LogChannel::Renderable3D, - "Model loading failed for character with model ID {:d}\n", modelId); - return false; - } - - InitMeshAnimStatus(); - ReloadDefaultBoneTransforms(); - - Animator.Character = this; - SwitchAnimation(StaticModel->IdleAnimation, 0.0f); - - IsUsed = true; - - return true; -} - -void Renderable3D::MakePlane() { - assert(IsUsed == false); - - StaticModel = Model::MakePlane(); - ModelTransform = Transform(); - PrevPoseWeight = 0.0f; - - Animator.Character = this; - - InitMeshAnimStatus(); - ReloadDefaultBoneTransforms(); - - IsUsed = true; -} - -void Renderable3D::InitMeshAnimStatus() { - int totalMorphedVertices = 0; - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - MeshAnimStatus[i].MorphedVerticesOffset = totalMorphedVertices; - if (StaticModel->Meshes[i].MorphTargetCount > 0) { - totalMorphedVertices += StaticModel->Meshes[i].VertexCount; - } - } - if (totalMorphedVertices > 0) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - Device->CreateVertexBuffer( - totalMorphedVertices * sizeof(VertexBufferDaSH), 0, 0, - D3DPOOL_MANAGED, &MorphedVerticesDevice, NULL); - } else { - Device->CreateVertexBuffer(totalMorphedVertices * sizeof(VertexBuffer), 0, - 0, D3DPOOL_MANAGED, &MorphedVerticesDevice, - NULL); - } - } - ReloadDefaultMeshAnimStatus(); -} - -void Renderable3D::ReloadDefaultMeshAnimStatus() { - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - MeshAnimStatus[i].Visible = 1.0f; - if (StaticModel->Meshes[i].MorphTargetCount > 0) { - for (uint8_t j = 0; j < StaticModel->Meshes[i].MorphTargetCount; j++) { - MeshAnimStatus[i].MorphInfluences[j] = 0.0f; - } - } - } -} - -void Renderable3D::SwitchAnimation(int16_t animId, float transitionTime) { - if (Animator.CurrentAnimation != 0 && transitionTime > 0.0f) { - PrevPoseWeight = 1.0f; - for (uint32_t i = 0; i < StaticModel->BoneCount; i++) { - PrevBoneTransforms[i] = CurrentPose[i].LocalTransform; - } - memcpy(PrevMeshAnimStatus, MeshAnimStatus, sizeof(MeshAnimStatus)); - AnimationTransitionTime = transitionTime; - } else { - PrevPoseWeight = 0.0f; - } - Animator.Start(animId); -} - -void Renderable3D::ReloadDefaultBoneTransforms() { - for (uint32_t i = 0; i < StaticModel->BoneCount; i++) { - CurrentPose[i].LocalTransform = StaticModel->Bones[i].BaseTransform; - } -} - -void Renderable3D::CalculateMorphedVertices(int id) { - Mesh* mesh = &StaticModel->Meshes[id]; - AnimatedMesh* animStatus = &MeshAnimStatus[id]; - AnimatedMesh* prevAnimStatus = &PrevMeshAnimStatus[id]; - if (mesh->MorphTargetCount == 0) return; - - void* currentMorphedVertex; - auto res = MorphedVerticesDevice->Lock(0, 0, &CurrentMorphedVerticesDx, 0); - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertex = ((VertexBufferDaSH*)CurrentMorphedVerticesDx) + - animStatus->MorphedVerticesOffset; - } else { - currentMorphedVertex = ((VertexBuffer*)CurrentMorphedVerticesDx) + - animStatus->MorphedVerticesOffset; - } - VertexBuffer* currentMorphedVertexRNE = (VertexBuffer*)currentMorphedVertex; - VertexBufferDaSH* currentMorphedVertexDaSH = - (VertexBufferDaSH*)currentMorphedVertex; - - void* currentVertex; - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentVertex = - ((VertexBufferDaSH*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } else { - currentVertex = - ((VertexBuffer*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } - - VertexBuffer* currentVertexRNE = (VertexBuffer*)currentVertex; - VertexBufferDaSH* currentVertexDaSH = (VertexBufferDaSH*)currentVertex; - - for (uint32_t j = 0; j < mesh->VertexCount; j++) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - memcpy(currentMorphedVertexDaSH, currentVertexDaSH, - sizeof(VertexBufferDaSH)); - currentMorphedVertexDaSH++; - currentVertexDaSH++; - } else { - memcpy(currentMorphedVertexRNE, currentVertexRNE, sizeof(VertexBuffer)); - currentMorphedVertexRNE++; - currentVertexRNE++; - } - } - - for (uint8_t k = 0; k < mesh->MorphTargetCount; k++) { - float influence; - if (PrevPoseWeight > 0.0f) { - influence = glm::mix(prevAnimStatus->MorphInfluences[k], - animStatus->MorphInfluences[k], - glm::smoothstep(0.0f, 1.0f, 1.0f - PrevPoseWeight)); - } else { - influence = animStatus->MorphInfluences[k]; - } - - if (influence == 0.0f) continue; - - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertex = ((VertexBufferDaSH*)CurrentMorphedVerticesDx) + - animStatus->MorphedVerticesOffset; - } else { - currentMorphedVertex = ((VertexBuffer*)CurrentMorphedVerticesDx) + - animStatus->MorphedVerticesOffset; - } - currentMorphedVertexRNE = (VertexBuffer*)currentMorphedVertex; - currentMorphedVertexDaSH = (VertexBufferDaSH*)currentMorphedVertex; - - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentVertex = - ((VertexBufferDaSH*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } else { - currentVertex = - ((VertexBuffer*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } - - currentVertexRNE = (VertexBuffer*)currentVertex; - currentVertexDaSH = (VertexBufferDaSH*)currentVertex; - - MorphVertexBuffer* currentMorphTargetVbo = - StaticModel->MorphVertexBuffers + - StaticModel->MorphTargets[mesh->MorphTargetIds[k]].VertexOffset; - - for (uint32_t j = 0; j < mesh->VertexCount; j++) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertexDaSH->Position += - (currentMorphTargetVbo->Position - currentVertexDaSH->Position) * - influence; - currentMorphedVertexDaSH->Normal += - (currentMorphTargetVbo->Normal - currentVertexDaSH->Normal) * - influence; - currentVertexDaSH++; - currentMorphedVertexDaSH++; - } else { - currentMorphedVertexRNE->Position += - (currentMorphTargetVbo->Position - currentVertexRNE->Position) * - influence; - currentMorphedVertexRNE->Normal += - (currentMorphTargetVbo->Normal - currentVertexRNE->Normal) * - influence; - currentVertexRNE++; - currentMorphedVertexRNE++; - } - currentMorphTargetVbo++; - } - } - - res = MorphedVerticesDevice->Unlock(); -} - -void Renderable3D::Pose() { - for (int i = 0; i < StaticModel->RootBoneCount; i++) { - PoseBone(StaticModel->RootBones[i]); - } -} - -void Renderable3D::PoseBone(int16_t id) { - StaticBone* bone = &StaticModel->Bones[id]; - PosedBone* transformed = &CurrentPose[id]; - - glm::mat4 parentWorld; - if (bone->Parent < 0) { - parentWorld = glm::mat4(1.0); - } else { - parentWorld = CurrentPose[bone->Parent].World; - } - - Transform transform; - if (PrevPoseWeight > 0.0f) { - transform = PrevBoneTransforms[id].Interpolate( - transformed->LocalTransform, - glm::smoothstep(0.0f, 1.0f, 1.0f - PrevPoseWeight)); - } else { - transform = transformed->LocalTransform; - } - - glm::mat4 local = transform.Matrix(); - - transformed->World = parentWorld * local; - - for (int i = 0; i < bone->ChildrenCount; i++) { - PoseBone(bone->Children[i]); - } - - transformed->Offset = transformed->World * bone->BindInverse; -} - -void Renderable3D::Update(float dt) { - if (!IsUsed) return; - if (Animator.CurrentAnimation) { - if (!Animator.IsPlaying) { - // oneshot ended - SwitchAnimation(StaticModel->IdleAnimation, AnimationTransitionTime); - } else { - Animator.Update(dt); - } - } - Pose(); - if (PrevPoseWeight > 0.0f) { - PrevPoseWeight -= dt / AnimationTransitionTime; - if (PrevPoseWeight < 0.0f) PrevPoseWeight = 0.0f; - } - - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - CalculateMorphedVertices(i); - } -} - -void Renderable3D::DrawMesh(int id, RenderPass pass) { - if (pass == RP_Outline && StaticModel->Type == ModelType_Background) return; - - if (!MeshAnimStatus[id].Visible) return; - - Mesh& mesh = StaticModel->Meshes[id]; - - if (pass == RP_First && mesh.Flags & MeshFlag_Later) return; - if (pass == RP_Second && !(mesh.Flags & MeshFlag_Later)) return; - - if (pass == RP_Outline) { - UseMaterial(MT_Outline); - } else { - UseMaterial(mesh.Material); - } - // Because of the above, we use CurrentMaterial later, not mesh.Material - - UseMesh(id); - - switch (CurrentMaterial) { - case MT_Background: { - int constexpr backgroundTextureTypes[] = {TT_ColorMap}; - SetTextures(id, backgroundTextureTypes, 1); - break; - } - case MT_Outline: { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - int constexpr outlineTextureTypes[] = {TT_DaSH_ColorMap, - TT_DaSH_NoiseMap}; - SetTextures(id, outlineTextureTypes, 2); - } else { - int constexpr outlineTextureTypes[] = {TT_ColorMap}; - SetTextures(id, outlineTextureTypes, 1); - } - break; - } - case MT_Generic: { - int constexpr genericTextureTypes[] = {TT_ColorMap, TT_GradientMaskMap, - TT_SpecularColorMap}; - SetTextures(id, genericTextureTypes, 3); - break; - } - case MT_Eye: { - int constexpr eyeTextureTypes[] = { - TT_Eye_IrisColorMap, TT_Eye_WhiteColorMap, TT_Eye_HighlightColorMap, - TT_Eye_IrisSpecularColorMap}; - SetTextures(id, eyeTextureTypes, 4); - break; - } - case MT_DaSH_Generic: { - int constexpr dashGenericTextureTypes[] = { - TT_DaSH_ColorMap, TT_DaSH_GradientMaskMap, TT_DaSH_SpecularColorMap, - TT_DaSH_ShadowColorMap}; - SetTextures(id, dashGenericTextureTypes, 4); - break; - } - case MT_DaSH_Face: - case MT_DaSH_Skin: { - int constexpr dashGenericTextureTypes[] = { - TT_DaSH_ColorMap, TT_DaSH_GradientMaskMap, TT_DaSH_SpecularColorMap}; - SetTextures(id, dashGenericTextureTypes, 3); - break; - } - case MT_DaSH_Eye: { - int constexpr dashEyeTextureTypes[] = {TT_DaSH_Eye_IrisColorMap, - TT_DaSH_Eye_WhiteColorMap, - TT_DaSH_Eye_HighlightColorMap}; - SetTextures(id, dashEyeTextureTypes, 3); - break; - } - case MT_None: - break; - } - - if (mesh.Opacity < 0.9 && CurrentMaterialIsDepthWrite) { - Device->SetRenderState(D3DRS_ZWRITEENABLE, 0); - } - - size_t stride = Profile::Scene3D::Version == LKMVersion::DaSH - ? sizeof(VertexBufferDaSH) - : sizeof(VertexBuffer); - if (StaticModel->Type == ModelType_Background) - stride = sizeof(BgVertexBuffer); - - if (StaticModel->Meshes[id].MorphTargetCount > 0) { - Device->SetStreamSource( - 0, MorphedVerticesDevice, - (UINT)(MeshAnimStatus[id].MorphedVerticesOffset * stride), - (UINT)stride); - - } else { - Device->SetStreamSource(0, MeshVertexBuffersDevice[id], 0, (UINT)stride); - } - Device->SetIndices(MeshIndexBuffersDevice[id]); - - Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mesh.IndexCount, 0, - mesh.IndexCount / 3); - - if (mesh.Opacity < 0.9 && CurrentMaterialIsDepthWrite) { - Device->SetRenderState(D3DRS_ZWRITEENABLE, 1); - } - - if (pass != RP_Outline) DrawMesh(id, RP_Outline); -} - -void Renderable3D::Render() { - if (!IsUsed || !IsVisible) return; - - memset(UniformsUpdated, 0, sizeof(UniformsUpdated)); - - for (int i = RP_First; i < RP_Count; i++) { - for (uint32_t j = 0; j < StaticModel->MeshCount; j++) { - DrawMesh(j, (RenderPass)i); - } - } - - if (CurrentMaterial == MT_Outline) { - // Clean up some state - UseMaterial(MT_Background); - } -} - -void Renderable3D::SetTextures(int id, int const* textureTypes, int count) { - for (int i = 0; i < count; i++) { - int t = textureTypes[i]; - if (StaticModel->Meshes[id].Maps[t] >= 0) { - Device->SetTexture(i, - Textures[TexBuffers[StaticModel->Meshes[id].Maps[t]]]); - } else { - Device->SetTexture(i, Textures[TextureDummy]); - } - } -} - -void Renderable3D::LoadModelUniforms() { - if (StaticModel->Type == ModelType_Character) { - ModelUniformBufferType entry{}; - entry.Model = ModelTransform.Matrix(); - Device->SetVertexShaderConstantF(7, glm::value_ptr(entry.Model), 4); - Device->SetPixelShaderConstantF(7, glm::value_ptr(entry.Model), 4); - } -} - -void Renderable3D::UseMaterial(MaterialType type) { - if (CurrentMaterial == type) return; - - switch (type) { - case MT_Outline: { - ShaderOutline->UseShader(Device); - break; - } - case MT_Background: { - ShaderBackground->UseShader(Device); - break; - } - case MT_Generic: - case MT_DaSH_Generic: - case MT_DaSH_Face: - case MT_DaSH_Skin: { - ShaderMain->UseShader(Device); - break; - } - case MT_Eye: - case MT_DaSH_Eye: { - ShaderEye->UseShader(Device); - break; - } - case MT_None: - break; - } - - SetSceneUniformValues(); - LoadModelUniforms(); - - if (type == MT_Outline) { - Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - } else { - Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); - } - - if (type == MT_Outline) { - CurrentMaterialIsDepthWrite = false; - } else { - CurrentMaterialIsDepthWrite = true; - } - - CurrentMaterial = type; -} - -void Renderable3D::UseMesh(int id) { LoadMeshUniforms(id); } - -void Renderable3D::LoadMeshUniforms(int id) { - Mesh& mesh = StaticModel->Meshes[id]; - - if (StaticModel->Type == ModelType_Character) { - MeshUniformBufferType entry{}; - if (mesh.UsedBones > 0) { - glm::mat4* outBone = entry.Bones; - for (uint32_t j = 0; j < mesh.UsedBones; j++) { - memcpy(outBone, glm::value_ptr(CurrentPose[mesh.BoneMap[j]].Offset), - sizeof(glm::mat4)); - outBone++; - } - } else { - entry.Bones[0] = CurrentPose[mesh.MeshBone].Offset; - } - - entry.ModelOpacity = mesh.Opacity; - entry.HasShadowColorMap = - mesh.Material == MT_DaSH_Generic && mesh.HasShadowColorMap; - - Device->SetVertexShaderConstantB(1, (BOOL*)&entry.HasShadowColorMap, 1); - Device->SetVertexShaderConstantF(11, &entry.ModelOpacity, 1); - Device->SetVertexShaderConstantF(12, (float*)&entry.Bones, - 4 * ModelMaxBonesPerMesh); - - Device->SetPixelShaderConstantB(1, (BOOL*)&entry.HasShadowColorMap, 1); - Device->SetPixelShaderConstantF(11, &entry.ModelOpacity, 1); - Device->SetPixelShaderConstantF(12, (float*)&entry.Bones, - 4 * ModelMaxBonesPerMesh); - } else if (StaticModel->Type == ModelType_Background) { - BgMVPUniformBufferType entry{}; - entry.MVP = ViewProjection * mesh.ModelTransform.Matrix(); - Device->SetVertexShaderConstantF(0, glm::value_ptr(entry.MVP), 4); - } -} - -void Renderable3D::UnloadSync() { - Animator.CurrentAnimation = 0; - PrevPoseWeight = 0.0f; - if (StaticModel) { - ImpLog(LogLevel::Info, LogChannel::Renderable3D, "Unloading model {:d}\n", - StaticModel->Id); - if (IsSubmitted) { - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - MeshVertexBuffersDevice[i]->Release(); - MeshIndexBuffersDevice[i]->Release(); - } - } - delete StaticModel; - StaticModel = 0; - } - if (MorphedVerticesDevice) { - MorphedVerticesDevice->Release(); - } - if (CurrentMorphedVertices) { - free(CurrentMorphedVertices); - CurrentMorphedVertices = 0; - } - ModelTransform = Transform(); - IsSubmitted = false; - IsUsed = false; - IsVisible = false; -} - -void Renderable3D::MainThreadOnLoad() { - assert(IsSubmitted == false); - - ImpLog(LogLevel::Info, LogChannel::Renderable3D, - "Submitting data to GPU for model ID {:d}\n", StaticModel->Id); - - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - if (StaticModel->Type == ModelType_Character) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - Device->CreateVertexBuffer( - sizeof(VertexBufferDaSH) * StaticModel->Meshes[i].VertexCount, 0, 0, - D3DPOOL_MANAGED, &MeshVertexBuffersDevice[i], NULL); - - VOID* pVoid; - auto res = MeshVertexBuffersDevice[i]->Lock(0, 0, (void**)&pVoid, 0); - memcpy(pVoid, - (VertexBufferDaSH*)StaticModel->VertexBuffers + - StaticModel->Meshes[i].VertexOffset, - sizeof(VertexBufferDaSH) * StaticModel->Meshes[i].VertexCount); - res = MeshVertexBuffersDevice[i]->Unlock(); - } else { - Device->CreateVertexBuffer( - sizeof(VertexBuffer) * StaticModel->Meshes[i].VertexCount, 0, 0, - D3DPOOL_MANAGED, &MeshVertexBuffersDevice[i], NULL); - - VOID* pVoid; - auto res = MeshVertexBuffersDevice[i]->Lock(0, 0, (void**)&pVoid, 0); - memcpy(pVoid, - (VertexBuffer*)StaticModel->VertexBuffers + - StaticModel->Meshes[i].VertexOffset, - sizeof(VertexBuffer) * StaticModel->Meshes[i].VertexCount); - res = MeshVertexBuffersDevice[i]->Unlock(); - } - } else if (StaticModel->Type == ModelType_Background) { - Device->CreateVertexBuffer( - sizeof(BgVertexBuffer) * StaticModel->Meshes[i].VertexCount, 0, 0, - D3DPOOL_MANAGED, &MeshVertexBuffersDevice[i], NULL); - - VOID* pVoid; - auto res = MeshVertexBuffersDevice[i]->Lock(0, 0, (void**)&pVoid, 0); - memcpy(pVoid, - (BgVertexBuffer*)StaticModel->VertexBuffers + - StaticModel->Meshes[i].VertexOffset, - sizeof(BgVertexBuffer) * StaticModel->Meshes[i].VertexCount); - res = MeshVertexBuffersDevice[i]->Unlock(); - } - - Device->CreateIndexBuffer( - sizeof(uint16_t) * StaticModel->Meshes[i].IndexCount, 0, D3DFMT_INDEX16, - D3DPOOL_MANAGED, &MeshIndexBuffersDevice[i], NULL); - VOID* pVoid; - auto res = MeshIndexBuffersDevice[i]->Lock(0, 0, (void**)&pVoid, 0); - memcpy(pVoid, StaticModel->Indices + StaticModel->Meshes[i].IndexOffset, - sizeof(uint16_t) * StaticModel->Meshes[i].IndexCount); - res = MeshIndexBuffersDevice[i]->Unlock(); - } - - for (uint32_t i = 0; i < StaticModel->TextureCount; i++) { - TexBuffers[i] = StaticModel->Textures[i].Submit(); - if (TexBuffers[i] == 0) { - ImpLog(LogLevel::Fatal, LogChannel::Renderable3D, - "Submitting texture {:d} for model {:d} failed\n", i, - StaticModel->Id); - } - } - - IsSubmitted = true; -} - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/3d/renderable3d.h b/src/renderer/dx9/3d/renderable3d.h deleted file mode 100644 index 7855d4f59..000000000 --- a/src/renderer/dx9/3d/renderable3d.h +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#ifndef NOMINMAX -#define NOMINMAX 1 -#endif - -#include "../shader.h" -#include "../window.h" -#include "../../3d/renderable3d.h" -#include "../utils.h" - -namespace Impacto { -namespace DirectX9 { - -enum RenderPass { RP_Outline = 0, RP_First = 1, RP_Second = 2, RP_Count }; - -struct SceneUniformBufferType { - glm::mat4 ViewProjection; - glm::vec4 Tint; - glm::vec3 WorldLightPosition; - glm::vec3 WorldEyePosition; - bool DarkMode; -}; - -struct ModelUniformBufferType { - glm::mat4 Model; -}; - -struct MeshUniformBufferType { - glm::mat4 Bones[ModelMaxBonesPerMesh]; - float ModelOpacity; - bool HasShadowColorMap; -}; - -struct BgMVPUniformBufferType { - glm::mat4 MVP; -}; - -class Renderable3D : public IRenderable3D { - public: - static void Init(DirectX9Window* window, IDirect3DDevice9* device); - static void BeginFrame(IScene3D* scene, Camera* camera); - - void MakePlane() override; - - void Update(float dt) override; - void Render() override; - - void ReloadDefaultBoneTransforms() override; - void InitMeshAnimStatus() override; - void ReloadDefaultMeshAnimStatus() override; - - void SwitchAnimation(int16_t animId, float transitionTime) override; - - protected: - bool LoadSync(uint32_t modelId) override; - void UnloadSync() override; - void MainThreadOnLoad() override; - - private: - void SetSceneUniformValues(); - - void Pose(); - void PoseBone(int16_t id); - - void CalculateMorphedVertices(int id); - - void UseMaterial(MaterialType type); - void UseMesh(int id); - void LoadModelUniforms(); - void LoadMeshUniforms(int id); - void SetTextures(int id, int const* textureUnits, int count); - void DrawMesh(int id, RenderPass pass); - - IDirect3DVertexBuffer9* MeshVertexBuffersDevice[ModelMaxMeshesPerModel]; - IDirect3DIndexBuffer9* MeshIndexBuffersDevice[ModelMaxMeshesPerModel]; - - void* CurrentMorphedVerticesDx; - IDirect3DVertexBuffer9* MorphedVerticesDevice; - - uint32_t TexBuffers[ModelMaxTexturesPerModel]; - - bool UniformsUpdated[ModelMaxMeshesPerModel]; - - Transform PrevBoneTransforms[ModelMaxBonesPerModel]; - AnimatedMesh PrevMeshAnimStatus[ModelMaxMeshesPerModel]; - float PrevPoseWeight; - float AnimationTransitionTime; -}; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/3d/scene.cpp b/src/renderer/dx9/3d/scene.cpp deleted file mode 100644 index 1462f2c71..000000000 --- a/src/renderer/dx9/3d/scene.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "scene.h" - -#include "../../3d/camera.h" -#include "../../../log.h" -#include "../../../workqueue.h" -#include "renderable3d.h" - -#include "../../../profile/scene3d.h" - -namespace Impacto { -namespace DirectX9 { - -Scene3D::Scene3D(DirectX9Window* window, IDirect3DDevice9* device) { - Window = window; - Device = device; -} - -void Scene3D::Init() { - assert(IsInit == false); - ImpLog(LogLevel::Info, LogChannel::Scene, "Initializing 3D scene system\n"); - IsInit = true; - - Profile::Scene3D::Configure(); - - Renderables = new IRenderable3D*[Profile::Scene3D::MaxRenderables]; - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - Renderables[i] = new Renderable3D(); - } - - Renderable3D::Init(Window, Device); - - MainCamera.Init(); - - // clang-format off - float ScreenFillingTriangle[] = { - // Position // UV - -1.0f, -1.0f, 0.0f, 0.0f, - 3.0f, -1.0f, 2.0f, 0.0f, - -1.0f, 3.0f, 0.0f, 2.0f - }; - // clang-format on -} - -void Scene3D::Shutdown() { - if (!IsInit) return; - if (Renderables) delete[] Renderables; -} - -void Scene3D::Update(float dt) { - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - if (Renderables[i]->Status == LoadStatus::Loaded) { - Renderables[i]->Update(dt); - } - } -} -void Scene3D::Render() { - RectF viewport = Window->GetViewport(); - MainCamera.AspectRatio = viewport.Width / viewport.Height; - MainCamera.Recalculate(); - - Renderable3D::BeginFrame(this, &MainCamera); - - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - if (Renderables[i]->Status == LoadStatus::Loaded && - Renderables[i]->StaticModel->Type == ModelType_Background) { - Renderables[i]->Render(); - } - } - - Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - if (Renderables[i]->Status == LoadStatus::Loaded && - Renderables[i]->StaticModel->Type == ModelType_Character) { - Renderables[i]->Render(); - } - } -} - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/3d/scene.h b/src/renderer/dx9/3d/scene.h deleted file mode 100644 index f51449d82..000000000 --- a/src/renderer/dx9/3d/scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#include "../../3d/scene.h" -#include "../window.h" -#include "../renderer.h" - -namespace Impacto { -namespace DirectX9 { - -class Scene3D : public IScene3D { - public: - Scene3D(DirectX9Window* window, IDirect3DDevice9* device); - - void Init(); - void Shutdown(); - void Update(float dt); - void Render(); - - private: - bool IsInit = false; - - DirectX9Window* Window; - IDirect3DDevice9* Device; -}; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/nv12frame.cpp b/src/renderer/dx9/nv12frame.cpp deleted file mode 100644 index 58b75f471..000000000 --- a/src/renderer/dx9/nv12frame.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "nv12frame.h" - -#include "../../log.h" - -namespace Impacto { -namespace DirectX9 { - -DX9NV12Frame::DX9NV12Frame(IDirect3DDevice9* device) { Device = device; } - -void DX9NV12Frame::Init(float width, float height) { - Width = width; - Height = height; - auto err = Device->CreateTexture((UINT)Width, (UINT)Height, 1, 0, D3DFMT_A8, - D3DPOOL_MANAGED, &Luma, nullptr); - err = Device->CreateTexture((UINT)(Width / 2), (UINT)(Height / 2), 1, 0, - D3DFMT_A8L8, D3DPOOL_MANAGED, &CbCr, nullptr); -} - -void Impacto::DirectX9::DX9NV12Frame::Submit(const void* luma, int lumaStride, - const void* cbcr, int cbcrStride) { - D3DLOCKED_RECT lockRect; - auto err = Luma->LockRect(0, &lockRect, NULL, 0); - const uint8_t* src = (const uint8_t*)luma; - uint8_t* dst = (uint8_t*)lockRect.pBits; - for (int y = 0; y < (int)Height; y++) { - memcpy(dst, src, (int)Width); - src += lumaStride; - dst += lockRect.Pitch; - } - - err = Luma->UnlockRect(0); - - err = CbCr->LockRect(0, &lockRect, NULL, 0); - - src = (const uint8_t*)cbcr; - dst = (uint8_t*)lockRect.pBits; - for (int y = 0; y < (int)Height / 2; y++) { - memcpy(dst, src, (int)Width); - src += cbcrStride; - dst += lockRect.Pitch; - } - - err = CbCr->UnlockRect(0); -} - -void DX9NV12Frame::Release() { - Luma->Release(); - CbCr->Release(); -} - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/nv12frame.h b/src/renderer/dx9/nv12frame.h deleted file mode 100644 index da09e0897..000000000 --- a/src/renderer/dx9/nv12frame.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "../nv12frame.h" - -#include - -namespace Impacto { -namespace DirectX9 { - -class DX9NV12Frame : public NV12Frame { - friend class Renderer; - - public: - DX9NV12Frame(IDirect3DDevice9* device); - - void Init(float width, float height) override; - - void Submit(const void* luma, int lumaStride, const void* cbcr, - int cbcrStride) override; - void Release() override; - - protected: - IDirect3DDevice9* Device; - - IDirect3DTexture9* Luma; - IDirect3DTexture9* CbCr; -}; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/renderer.cpp b/src/renderer/dx9/renderer.cpp deleted file mode 100644 index 0bfbf4754..000000000 --- a/src/renderer/dx9/renderer.cpp +++ /dev/null @@ -1,860 +0,0 @@ -#include "renderer.h" - -#include - -#include "../../profile/game.h" -#include "../../game.h" -#include "../../log.h" -#include "3d/scene.h" -#include "utils.h" - -#ifndef IMPACTO_DISABLE_IMGUI -#include -#endif - -namespace Impacto { -namespace DirectX9 { - -void Renderer::Init() { - if (IsInit) return; - ImpLog(LogLevel::Info, LogChannel::Render, - "Initializing Renderer2D DirectX 9 system\n"); - IsInit = true; - - DXWindow = new DirectX9Window(); - DXWindow->Init(); - Window = (BaseWindow*)DXWindow; - - Interface = Direct3DCreate9(D3D_SDK_VERSION); - - HWND hWnd = - (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(Window->SDLWindow), - SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); - - D3DPRESENT_PARAMETERS d3dpp{}; - d3dpp.Windowed = TRUE; - d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; - d3dpp.hDeviceWindow = hWnd; - d3dpp.EnableAutoDepthStencil = TRUE; - d3dpp.AutoDepthStencilFormat = D3DFMT_D16; - - Interface->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, - D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &Device); - Device->CreateVertexBuffer(VertexBufferSize, 0, 0, D3DPOOL_MANAGED, - &VertexBufferDevice, NULL); - Device->CreateIndexBuffer(IndexBufferCount * sizeof(uint16_t), 0, - D3DFMT_INDEX16, D3DPOOL_MANAGED, &IndexBufferDevice, - NULL); - - Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); - Device->SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD); - Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - Device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_SRCALPHA); - Device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA); - Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - - IDirect3DVertexDeclaration9* vertexDeclaration; - std::vector vertexDeclDesc{ - {0, offsetof(VertexBufferSprites, Position), D3DDECLTYPE_FLOAT2, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, - {0, offsetof(VertexBufferSprites, UV), D3DDECLTYPE_FLOAT2, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, - {0, offsetof(VertexBufferSprites, Tint), D3DDECLTYPE_FLOAT4, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, - {0, offsetof(VertexBufferSprites, MaskUV), D3DDECLTYPE_FLOAT2, - D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, - D3DDECL_END()}; - Device->CreateVertexDeclaration(vertexDeclDesc.data(), &vertexDeclaration); - - ShaderSprite = new Shader(); - ShaderSprite->Compile("Sprite", Device, vertexDeclaration); - ShaderSpriteInverted = new Shader(); - ShaderSpriteInverted->Compile("Sprite_inverted", Device, vertexDeclaration); - ShaderMaskedSprite = new Shader(); - ShaderMaskedSprite->Compile("MaskedSprite", Device, vertexDeclaration); - ShaderMaskedSpriteNoAlpha = new Shader(); - ShaderMaskedSpriteNoAlpha->Compile("MaskedSpriteNoAlpha", Device, - vertexDeclaration); - ShaderYUVFrame = new Shader(); - ShaderYUVFrame->Compile("YUVFrame", Device, vertexDeclaration); - ShaderNV12Frame = new Shader(); - ShaderNV12Frame->Compile("NV12Frame", Device, vertexDeclaration); - ShaderCCMessageBox = new Shader(); - ShaderCCMessageBox->Compile("CCMessageBoxSprite", Device, vertexDeclaration); - ShaderCHLCCMenuBackground = new Shader(); - ShaderCHLCCMenuBackground->Compile("CHLCCMenuBackground", Device, - vertexDeclaration); - - CurrentShader = ShaderSprite; - CurrentShader->UseShader(Device); - - if (+Profile::Game::GameFeatures & +GameFeature::Scene3D) { - Scene = new Scene3D(DXWindow, Device); - Scene->Init(); - } - - // Fill index buffer with quads - size_t index = 0; - uint16_t vertex = 0; - while (index + 6 <= IndexBufferCount) { - // bottom-left -> top-left -> top-right - IndexBuffer[index] = vertex + 0; - IndexBuffer[index + 1] = vertex + 1; - IndexBuffer[index + 2] = vertex + 2; - // bottom-left -> top-right -> bottom-right - IndexBuffer[index + 3] = vertex + 0; - IndexBuffer[index + 4] = vertex + 2; - IndexBuffer[index + 5] = vertex + 3; - index += 6; - vertex += 4; - } - - // Make 1x1 white pixel for colored rectangles - Texture rectTexture; - rectTexture.Load1x1(0xFF, 0xFF, 0xFF, 0xFF); - SpriteSheet rectSheet(1.0f, 1.0f); - rectSheet.Texture = rectTexture.Submit(); - RectSprite = Sprite(rectSheet, 0.0f, 0.0f, 1.0f, 1.0f); - -#ifndef IMPACTO_DISABLE_IMGUI - // Setup Platform/Renderer backends - ImGui_ImplSDL3_InitForD3D(DXWindow->SDLWindow); - ImGui_ImplDX9_Init(Device); -#endif -} - -void Renderer::Shutdown() { - if (!IsInit) return; - IsInit = false; - - if (+Profile::Game::GameFeatures & +GameFeature::Scene3D) { - Scene->Shutdown(); - } - - VertexBufferDevice->Release(); - IndexBufferDevice->Release(); - Device->Release(); - Interface->Release(); -} - -#ifndef IMPACTO_DISABLE_IMGUI -void Renderer::ImGuiBeginFrame() { - ImGui_ImplDX9_NewFrame(); - ImGui_ImplSDL3_NewFrame(); - ImGui::NewFrame(); -} -#endif - -void Renderer::BeginFrame() { - if (Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->BeginFrame() called before EndFrame()\n"); - return; - } - - Drawing = true; - VertexBufferFill = 0; - IndexBufferFill = 0; - - Device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, - D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); - Device->BeginScene(); -} - -void Renderer::BeginFrame2D() { - Device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - Device->SetRenderState(D3DRS_ZWRITEENABLE, 0); - Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); -} - -void Renderer::EndFrame() { - if (!Drawing) return; - Flush(); - Drawing = false; - -#ifndef IMPACTO_DISABLE_IMGUI - ImGui::Render(); - ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); -#endif - - Device->EndScene(); - Device->Present(NULL, NULL, NULL, NULL); - CurrentShader = 0; - CurrentTexture = std::numeric_limits::max(); -} - -uint32_t Renderer::SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) { - int imageSize = 0; - D3DFORMAT imageFormat = D3DFMT_A1; - uint8_t* newBuffer = nullptr; - - switch (format) { - case TexFmt_RGBA: { - imageSize = width * height * 4; - imageFormat = D3DFMT_A8R8G8B8; - newBuffer = (uint8_t*)malloc(imageSize); - int num = width * height; - for (int i = 0; i < num; i++) { - newBuffer[4 * i] = buffer[4 * i + 2]; - newBuffer[4 * i + 1] = buffer[4 * i + 1]; - newBuffer[4 * i + 2] = buffer[4 * i]; - newBuffer[4 * i + 3] = buffer[4 * i + 3]; - } - } break; - case TexFmt_RGB: { - imageSize = width * height * 4; - imageFormat = D3DFMT_A8R8G8B8; - newBuffer = (uint8_t*)malloc(imageSize); - int num = width * height; - for (int i = 0; i < num; i++) { - newBuffer[4 * i] = buffer[3 * i + 2]; - newBuffer[4 * i + 1] = buffer[3 * i + 1]; - newBuffer[4 * i + 2] = buffer[3 * i]; - newBuffer[4 * i + 3] = 0xff; - } - } break; - case TexFmt_U8: - imageSize = width * height; - imageFormat = D3DFMT_A8; - default: { - } - } - - IDirect3DTexture9* texture; - auto err = Device->CreateTexture(width, height, 1, 0, imageFormat, - D3DPOOL_MANAGED, &texture, nullptr); - D3DLOCKED_RECT lockRect; - err = texture->LockRect(0, &lockRect, NULL, 0); - - if (format == TexFmt_RGBA || format == TexFmt_RGB) { - memcpy(lockRect.pBits, newBuffer, imageSize); - free(newBuffer); - } else { - memcpy(lockRect.pBits, buffer, imageSize); - } - - if (FAILED(texture->UnlockRect(0))) { - ImpLog(LogLevel::Error, LogChannel::Render, "Failed to load texture!\n"); - Window->Shutdown(); - } - - auto id = NextTextureId; - NextTextureId += 1; - Textures[id] = texture; - - return id; -} - -void Renderer::FreeTexture(uint32_t id) { - auto textureItr = Textures.find(id); - if (textureItr != Textures.end()) { - if (textureItr->second != nullptr) { - textureItr->second->Release(); - } - Textures.erase(textureItr); - } -} - -YUVFrame* Renderer::CreateYUVFrame(float width, float height) { - VideoFrameInternalYUV = new DX9YUVFrame(Device); - VideoFrameInternalYUV->Init(width, height); - return (YUVFrame*)VideoFrameInternalYUV; -} - -NV12Frame* Renderer::CreateNV12Frame(float width, float height) { - VideoFrameInternalNV12 = new DX9NV12Frame(Device); - VideoFrameInternalNV12->Init(width, height); - return (NV12Frame*)VideoFrameInternalNV12; -} - -void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, - const glm::mat4 transformation, - const std::span tints, - const glm::vec3 colorShift, const bool inverted, - const bool disableBlend, - const bool textureWrapRepeat) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawSprite() called before BeginFrame()\n"); - return; - } - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - // Are we in sprite mode? - if (inverted) - EnsureShader(ShaderSpriteInverted); - else - EnsureShader(ShaderSprite); - - // Do we have the texture assigned? - EnsureTextureBound(sprite.Sheet.Texture); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetPosition(CornersQuad(dest).Transform(transformation), - &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tints[i]; -} - -void Renderer::DrawMaskedSprite( - const Sprite& sprite, const Sprite& mask, const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, const int fadeRange, - const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, - const std::span tints, const bool isInverted, - const bool isSameTexture) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawMaskedSpriteOverlay() called before BeginFrame()\n"); - return; - } - - if (sprite.Sheet.IsScreenCap) Flush(); - - alpha = std::clamp(alpha, 0, fadeRange + 256); - const float alphaRange = 256.0f / fadeRange; - const float constAlpha = ((255.0f - alpha) * alphaRange) / 255.0f; - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - std::array alphaRes = {alphaRange, constAlpha, 0.0f, 0.0f}; - const BOOL isInvertedB = (BOOL)isInverted; - const BOOL isSameTextureB = (BOOL)isSameTexture; - - Flush(); - - EnsureShader(ShaderMaskedSprite); - Device->SetTexture(0, Textures[sprite.Sheet.Texture]); - Device->SetTexture(1, Textures[mask.Sheet.Texture]); - - Device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - Device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - Device->SetPixelShaderConstantF(0, alphaRes.data(), 1); - Device->SetPixelShaderConstantB(0, &isInvertedB, 1); - Device->SetPixelShaderConstantB(1, &isSameTextureB, 1); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(CornersQuad(maskDest).Transform(maskTransformation), - sprite.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(CornersQuad(spriteDest).Transform(spriteTransformation), - &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tints[i]; -} - -void Renderer::DrawMaskedSpriteOverlay( - const Sprite& sprite, const Sprite& mask, const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, const int fadeRange, - const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, - const std::span tints, const bool isInverted, - const bool useMaskAlpha) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawMaskedSpriteOverlay() called before BeginFrame()\n"); - return; - } - - if (sprite.Sheet.IsScreenCap) Flush(); - - if (alpha < 0) alpha = 0; - if (alpha > fadeRange + 256) alpha = fadeRange + 256; - - float alphaRange = 256.0f / fadeRange; - float constAlpha = ((255.0f - alpha) * alphaRange) / 255.0f; - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - std::array alphaRes = {alphaRange, constAlpha, 0.0f, 0.0f}; - BOOL isInvertedB = (BOOL)isInverted; - BOOL isSameTextureB = (BOOL) false; - - if (useMaskAlpha) { - EnsureShader(ShaderMaskedSprite); - Device->SetPixelShaderConstantB(1, &isSameTextureB, 1); - } else { - EnsureShader(ShaderMaskedSpriteNoAlpha); - } - - Device->SetTexture(0, Textures[sprite.Sheet.Texture]); - Device->SetTexture(1, Textures[mask.Sheet.Texture]); - - Device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - Device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - Device->SetPixelShaderConstantF(0, alphaRes.data(), 1); - Device->SetPixelShaderConstantB(0, &isInvertedB, 1); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(CornersQuad(maskDest).Transform(maskTransformation), - mask.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(CornersQuad(spriteDest).Transform(spriteTransformation), - &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tints[i]; -} - -void Renderer::DrawPrimitives( - const SpriteSheet& sheet, const SpriteSheet* const mask, - const ShaderProgramType shaderType, - const std::span vertices, - const std::span indices, - const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, - const bool inverted, TopologyMode topologyMode, bool textureWrapRepeat) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawVertices() called before BeginFrame()\n"); - return; - } - - // The index buffer needs to be flushed - Flush(); - - if (mask != nullptr) { - std::array alphaRes = {1.0f, 0.0f, 0.0f, 0.0f}; - BOOL isInvertedB = (BOOL)inverted; - - EnsureShader(ShaderMaskedSpriteNoAlpha); - - Device->SetTexture(0, Textures[sheet.Texture]); - Device->SetTexture(1, Textures[mask->Texture]); - - Device->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - Device->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - Device->SetPixelShaderConstantF(0, alphaRes.data(), 1); - Device->SetPixelShaderConstantB(0, &isInvertedB, 1); - - } else { - if (inverted) - EnsureShader(ShaderSpriteInverted); - else - EnsureShader(ShaderSprite); - - EnsureTextureBound(sheet.Texture); - } - - // Push vertices - VertexBufferSprites* vertexBuffer = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += vertices.size_bytes(); - - const auto vertexInfoToNDC = [this, spriteTransformation, - maskTransformation](VertexBufferSprites info) { - info.Position = DesignToNDC( - glm::vec2(spriteTransformation * glm::vec4(info.Position, 0.0f, 1.0f))); - info.MaskUV = - glm::vec2(maskTransformation * glm::vec4(info.MaskUV, 0.0f, 1.0f)); - return info; - }; - std::transform(vertices.begin(), vertices.end(), vertexBuffer, - vertexInfoToNDC); - - // Push indices - IndexBufferFill += indices.size(); - std::ranges::copy(indices, IndexBuffer); - - // Flush again and bind back our buffer - Flush(); - - // ReFill index buffer with quads - size_t index = 0; - uint16_t vertex = 0; - while (index + 6 <= IndexBufferCount) { - // bottom-left -> top-left -> top-right - IndexBuffer[index] = vertex + 0; - IndexBuffer[index + 1] = vertex + 1; - IndexBuffer[index + 2] = vertex + 2; - // bottom-left -> top-right -> bottom-right - IndexBuffer[index + 3] = vertex + 0; - IndexBuffer[index + 4] = vertex + 2; - IndexBuffer[index + 5] = vertex + 3; - index += 6; - vertex += 4; - } -} - -void Renderer::DrawCCMessageBox(Sprite const& sprite, Sprite const& mask, - RectF const& dest, glm::vec4 tint, int alpha, - int fadeRange, float effectCt) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawCCMessageBox() called before BeginFrame()\n"); - return; - } - - if (alpha < 0) alpha = 0; - if (alpha > fadeRange + 256) alpha = fadeRange + 256; - - float alphaRange = 256.0f / fadeRange; - float constAlpha = ((255.0f - alpha) * alphaRange) / 255.0f; - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - EnsureShader(ShaderCCMessageBox); - - Device->SetTexture(0, Textures[sprite.Sheet.Texture]); - CurrentTexture = sprite.Sheet.Texture; - Device->SetTexture(1, Textures[mask.Sheet.Texture]); - - // This is cursed man, idk - float alphaRes[] = {alphaRange, constAlpha, effectCt, 0.0f}; - Device->SetPixelShaderConstantF(0, alphaRes, 1); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(mask.Bounds, mask.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tint; -} - -void Renderer::DrawCHLCCMenuBackground(const Sprite& sprite, const Sprite& mask, - const RectF& dest, float alpha) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawCHLCCMenuBackground() called before BeginFrame()\n"); - return; - } - - if (alpha < 0.0f) - alpha = 0; - else if (alpha > 1.0f) - alpha = 1.0f; - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - EnsureShader(ShaderCHLCCMenuBackground); - - Device->SetTexture(0, Textures[sprite.Sheet.Texture]); - CurrentTexture = sprite.Sheet.Texture; - Device->SetTexture(1, Textures[mask.Sheet.Texture]); - - // This is cursed man, idk - float alphaRes[] = {alpha, 0.0f, 0.0f, 0.0f}; - Device->GetPixelShaderConstantF(0, alphaRes, 1); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUVFlipped(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - - QuadSetUV(mask.Bounds, mask.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) - vertices[i].Tint = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); -} - -void Renderer::EnsureSpaceAvailable(int vertices, int vertexSize, int indices) { - if (VertexBufferFill + vertices * vertexSize > VertexBufferSize || - IndexBufferFill + indices > IndexBufferCount) { - ImpLogSlow( - LogLevel::Trace, LogChannel::Render, - "Renderer->EnsureSpaceAvailable flushing because buffers full at " - "VertexBufferFill=0x{:08x},IndexBufferFill=0x{:08x}\n", - VertexBufferFill, IndexBufferFill); - Flush(); - } -} - -void Renderer::EnsureTextureBound(uint32_t texture) { - if (CurrentTexture != texture) { - ImpLogSlow(LogLevel::Trace, LogChannel::Render, - "Renderer->EnsureTextureBound flushing because texture {:d} is " - "not {:d}\n", - CurrentTexture, texture); - Flush(); - Device->SetTexture(0, Textures[texture]); - CurrentTexture = texture; - } -} - -void Renderer::EnsureShader(Shader* shader, bool flush) { - if (CurrentShader != shader) { - ImpLogSlow(LogLevel::Debug, LogChannel::Render, - "Renderer2D changing mode\n"); - if (flush) Flush(); - shader->UseShader(Device); - CurrentShader = shader; - } -} - -void Renderer::Flush() { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->Flush() called before BeginFrame()\n"); - return; - } - - if (VertexBufferFill > 0 && IndexBufferFill > 0) { - VOID* pVoid; - auto res = VertexBufferDevice->Lock(0, 0, (void**)&pVoid, 0); - memcpy(pVoid, VertexBuffer, VertexBufferFill); - res = VertexBufferDevice->Unlock(); - - res = IndexBufferDevice->Lock(0, 0, (void**)&pVoid, 0); - memcpy(pVoid, IndexBuffer, IndexBufferFill * sizeof(uint16_t)); - res = IndexBufferDevice->Unlock(); - - auto result = Device->SetStreamSource(0, VertexBufferDevice, 0, - sizeof(VertexBufferSprites)); - if (FAILED(result)) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to set stream source!\n"); - Window->Shutdown(); - } - - result = Device->SetIndices(IndexBufferDevice); - if (FAILED(result)) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to set stream indices!\n"); - Window->Shutdown(); - } - - result = Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, - (UINT)IndexBufferFill, 0, - (UINT)(IndexBufferFill / 3)); - if (FAILED(result)) { - ImpLog(LogLevel::Debug, LogChannel::Render, "Failed to draw!\n"); - Window->Shutdown(); - } - } - IndexBufferFill = 0; - VertexBufferFill = 0; - CurrentTexture = std::numeric_limits::max(); -} - -void Renderer::DrawVideoTexture(const YUVFrame& frame, const RectF& dest, - const glm::vec4 tint, const bool alphaVideo) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawVideoTexture() called before BeginFrame()\n"); - return; - } - - EnsureShader(ShaderYUVFrame); - CurrentTexture = std::numeric_limits::max(); - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - auto err = Device->SetTexture(0, VideoFrameInternalYUV->Luma); - err = Device->SetTexture(1, VideoFrameInternalYUV->Cb); - err = Device->SetTexture(2, VideoFrameInternalYUV->Cr); - - // This is cursed man, idk - BOOL alphaVideoB = (BOOL)alphaVideo; - Device->SetPixelShaderConstantB(0, &alphaVideoB, 1); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUV(RectF(0.0f, 0.0f, frame.Width, frame.Height), - {frame.Width, frame.Height}, &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tint; -} - -void Renderer::DrawVideoTexture(const NV12Frame& frame, const RectF& dest, - const glm::vec4 tint, const bool alphaVideo) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawVideoTexture() called before BeginFrame()\n"); - return; - } - - EnsureShader(ShaderNV12Frame); - CurrentTexture = std::numeric_limits::max(); - - // Do we have space for one more sprite quad? - EnsureSpaceAvailable(4, sizeof(VertexBufferSprites), 6); - - auto err = Device->SetTexture(0, VideoFrameInternalNV12->Luma); - err = Device->SetTexture(1, VideoFrameInternalNV12->CbCr); - - // This is cursed man, idk - BOOL alphaVideoB = (BOOL)alphaVideo; - Device->SetPixelShaderConstantB(0, &alphaVideoB, 1); - - // OK, all good, make quad - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - IndexBufferFill += 6; - - QuadSetUV(RectF(0.0f, 0.0f, frame.Width, frame.Height), - {frame.Width, frame.Height}, &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tint; -} - -void Renderer::CaptureScreencap(Sprite& sprite) { - Flush(); - if (sprite.Sheet.Texture != 0) { - FreeTexture(sprite.Sheet.Texture); - } - - sprite.Sheet.IsScreenCap = true; - - IDirect3DSurface9* sourceSurface = nullptr; - Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &sourceSurface); - - D3DSURFACE_DESC backBufferDesc; - sourceSurface->GetDesc(&backBufferDesc); - - sprite.Sheet.DesignWidth = static_cast(backBufferDesc.Width); - sprite.Sheet.DesignHeight = static_cast(backBufferDesc.Height); - sprite.Bounds = RectF{0.0f, 0.0f, static_cast(backBufferDesc.Width), - static_cast(backBufferDesc.Height)}; - sprite.BaseScale = {Profile::Game::DesignWidth / backBufferDesc.Width, - Profile::Game::DesignHeight / backBufferDesc.Height}; - - IDirect3DTexture9* texture; - Device->CreateTexture(backBufferDesc.Width, backBufferDesc.Height, 1, - D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, - &texture, nullptr); - auto id = NextTextureId; - NextTextureId += 1; - Textures[id] = texture; - sprite.Sheet.Texture = id; - - IDirect3DSurface9* destSurface = nullptr; - texture->GetSurfaceLevel(0, &destSurface); - Device->StretchRect(sourceSurface, nullptr, destSurface, nullptr, - D3DTEXF_NONE); - - sourceSurface->Release(); - destSurface->Release(); -} - -void Renderer::EnableScissor() { - Flush(); - Device->SetRenderState(D3DRS_SCISSORTESTENABLE, true); -} - -void Renderer::SetScissorRect(RectF const& rect) { - Rect viewport = Window->GetViewport(); - float scale = fmin((float)Window->WindowWidth / Profile::Game::DesignWidth, - (float)Window->WindowHeight / Profile::Game::DesignHeight); - float rectX = rect.X * scale; - float rectY = rect.Y * scale; - float rectWidth = rect.Width * scale; - float rectHeight = rect.Height * scale; - - RECT rectW{}; - rectW.left = (LONG)rectX; - rectW.top = (LONG)rectY; - rectW.right = (LONG)(rect.X + rectWidth); - rectW.bottom = (LONG)(rect.Y + rectHeight); - Device->SetScissorRect(&rectW); -} - -void Renderer::DisableScissor() { - Flush(); - Device->SetRenderState(D3DRS_SCISSORTESTENABLE, false); -} - -glm::vec2 Renderer::DesignToNDC(glm::vec2 designCoord) const { - glm::vec2 result; - result.x = (designCoord.x / (Profile::Game::DesignWidth * 0.5f)) - 1.0f; - result.y = 1.0f - (designCoord.y / (Profile::Game::DesignHeight * 0.5f)); - return result; -} - -void Renderer::SetBlendMode(RendererBlendMode blendMode) { - Flush(); - - switch (blendMode) { - case RendererBlendMode::Normal: - Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - break; - case RendererBlendMode::Additive: - Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); - Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - break; - case RendererBlendMode::Premultiplied: - Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); - Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - break; - } -} - -void Renderer::Clear(glm::vec4 color) { - Flush(); - - color *= 255; - D3DCOLOR clearColor = - D3DCOLOR_ARGB((BYTE)color.a, (BYTE)color.r, (BYTE)color.g, (BYTE)color.b); - Device->Clear(0, NULL, D3DCLEAR_TARGET, clearColor, 1.0f, 0); -} - -} // namespace DirectX9 -} // namespace Impacto diff --git a/src/renderer/dx9/renderer.h b/src/renderer/dx9/renderer.h deleted file mode 100644 index 3c4d9360c..000000000 --- a/src/renderer/dx9/renderer.h +++ /dev/null @@ -1,179 +0,0 @@ -#pragma once - -#include "../renderer.h" -#include "window.h" -#include "shader.h" -#include "yuvframe.h" -#include "nv12frame.h" - -#include - -namespace Impacto { -namespace DirectX9 { - -class Renderer : public BaseRenderer { - public: - void Init() override; - void Shutdown() override; - -#ifndef IMPACTO_DISABLE_IMGUI - void ImGuiBeginFrame() override; -#endif - - void BeginFrame() override; - void BeginFrame2D() override; - void EndFrame() override; - - uint32_t MapSpriteSheet(SpriteSheet const& sheet) override { return 0; }; - bool LoadSurf(int surfId, int archiveId, int fileId) override { - return false; - }; - void UnloadSurf(int surfId) override {}; - uint32_t SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) override; - - int GetSpriteSheetImage(SpriteSheet const& sheet, - std::span outBuffer) override { - // TODO implement - return 0; - } - void FreeTexture(uint32_t id) override; - YUVFrame* CreateYUVFrame(float width, float height) override; - NV12Frame* CreateNV12Frame(float width, float height) override; - - void DrawSprite(const Sprite& sprite, const CornersQuad& dest, - glm::mat4 transformation, std::span tints, - glm::vec3 colorShift, bool inverted, bool disableBlend, - bool textureWrapRepeat) override; - - void DrawMaskedSprite(const Sprite& sprite, const Sprite& mask, - const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, int fadeRange, - glm::mat4 spriteTransformation, - glm::mat4 maskTransformation, - std::span tints, bool isInverted, - bool isSameTexture) override; - - // TODO: implement - void DrawMaskedBinarySprite(const Sprite& sprite, const Sprite& mask, - const CornersQuad& spriteDest, - const CornersQuad& maskDest, - glm::mat4 spriteTransformation, - std::optional maskTransformation, - std::span tints, - bool isInverted) override {} - - void DrawMaskedSpriteOverlay(const Sprite& sprite, const Sprite& mask, - const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, - int fadeRange, glm::mat4 spriteTransformation, - glm::mat4 maskTransformation, - std::span tints, - bool isInverted, bool useMaskAlpha) override; - - void DrawPrimitives(const SpriteSheet& sheet, const SpriteSheet* mask, - ShaderProgramType shaderType, - std::span vertices, - std::span indices, - glm::mat4 spriteTransformation, - glm::mat4 maskTransformation, bool inverted, - TopologyMode topologyMode, - bool textureWrapRepeat = false) override; - - void DrawCCMessageBox(Sprite const& sprite, Sprite const& mask, - RectF const& dest, glm::vec4 tint, int alpha, - int fadeRange, float effectCt) override; - - void DrawEdgeDetectedSingleSheetFont( - const SpriteSheet& sheet, const SpriteSheet* mask, - std::span vertices, - std::span indices, float differenceFactor, - float intensityShift, float alphaShift, glm::vec2 renderScale, - glm::mat4 spriteTransformation, glm::mat4 maskTransformation) override { - } // TODO: Implement - - void DrawCHLCCMenuBackground(const Sprite& sprite, const Sprite& mask, - const RectF& dest, float alpha) override; - - void DrawBlurredSprite(const Sprite& sprite, const CornersQuad& dest, - glm::mat4 transformation, - RendererBlurDirection blurDirection, - glm::vec4 tint) override {}; // TODO: Implement - - void DrawMosaic(const Sprite& sprite, const CornersQuad dest, float tileSize, - glm::mat4 transformation, - glm::vec4 tint) override {}; // TODO: Implement - - void DrawVideoTexture(const YUVFrame& frame, const RectF& dest, - glm::vec4 tint, bool alphaVideo) override; - void DrawVideoTexture(const NV12Frame& frame, const RectF& dest, - glm::vec4 tint, bool alphaVideo = false) override; - void DrawSubtitleGlyph(const Sprite& sprite, const CornersQuad& dest, - const glm::mat4 transformation, - const glm::vec4 tint) override {}; // TODO: Implement - - void CaptureScreencap(Sprite& sprite) override; - - void SetFramebuffer(size_t buffer) override {}; // TODO: Implement - int GetFramebufferTexture(size_t buffer) override { - return 0; - }; // TODO: Implement - - void EnableScissor() override; - void SetScissorRect(RectF const& rect) override; - void DisableScissor() override; - - void SetStencilMode(StencilBufferMode mode) override {}; // TODO: implement - void ClearStencilBuffer() override {}; // TODO: implement - - void SetBlendMode(RendererBlendMode blendMode) override; - - void Clear(glm::vec4 color) override; - - private: - void EnsureSpaceAvailable(int vertices, int vertexSize, int indices); - void EnsureTextureBound(uint32_t texture); - void EnsureShader(Shader* shader, bool flush = true); - void Flush() override; - - glm::vec2 DesignToNDC(glm::vec2 designCoord) const override; - - DirectX9Window* DXWindow; - - IDirect3D9* Interface; - IDirect3DDevice9* Device; - - Shader* CurrentShader; - - Shader* ShaderSprite; - Shader* ShaderSpriteInverted; - Shader* ShaderMaskedSprite; - Shader* ShaderMaskedSpriteNoAlpha; - Shader* ShaderYUVFrame; - Shader* ShaderNV12Frame; - Shader* ShaderCCMessageBox; - Shader* ShaderCHLCCMenuBackground; - - uint32_t CurrentTexture = 0; - uint32_t NextTextureId = 1; - - DX9YUVFrame* VideoFrameInternalYUV; - DX9NV12Frame* VideoFrameInternalNV12; - - bool Drawing = false; - - static int constexpr VertexBufferSize = 1024 * 1024; - static int constexpr IndexBufferCount = - VertexBufferSize / (4 * sizeof(VertexBufferSprites)) * 6; - - uint8_t VertexBuffer[VertexBufferSize]; - IDirect3DVertexBuffer9* VertexBufferDevice; - size_t VertexBufferFill = 0; - uint16_t IndexBuffer[IndexBufferCount]; - IDirect3DIndexBuffer9* IndexBufferDevice; - IDirect3DIndexBuffer9* IndexBufferMvl; - size_t IndexBufferFill = 0; -}; - -} // namespace DirectX9 -} // namespace Impacto diff --git a/src/renderer/dx9/shader.cpp b/src/renderer/dx9/shader.cpp deleted file mode 100644 index 9af65d373..000000000 --- a/src/renderer/dx9/shader.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "shader.h" - -#include - -#include "renderer.h" -#include "../../log.h" - -namespace Impacto { -namespace DirectX9 { - -static char const ShaderPath[] = "./shaders/dx9"; -static char const FragShaderExtension[] = "_frag.hlsl"; -static char const VertShaderExtension[] = "_vert.hlsl"; - -void Shader::Compile(char const* name, IDirect3DDevice9* device, - IDirect3DVertexDeclaration9* vertexDeclaration, - D3D_SHADER_MACRO* macros) { - ImpLog(LogLevel::Debug, LogChannel::Render, "Compiling shader \"{:s}\"\n", - name); - - VertexDeclaration = vertexDeclaration; - - ID3DBlob* vertexShaderBuffer{}; - ID3DBlob* errorBlob{}; - ID3DBlob* pixelShaderBuffer{}; - - // Vertex shader - std::string vertexShaderPath = fmt::format(FMT_COMPILE("{}/{}{}"), ShaderPath, - name, VertShaderExtension); - size_t sourceRawSz; - char* source = (char*)SDL_LoadFile(vertexShaderPath.c_str(), &sourceRawSz); - if (!source) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to read shader source file\n"); - return; - } - auto result = - D3DCompile(source, sourceRawSz, nullptr, macros, nullptr, "main", - "vs_3_0", 0, 0, &vertexShaderBuffer, &errorBlob); - if (FAILED(result)) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to compile shader source file {:s}\n", - static_cast(errorBlob->GetBufferPointer())); - return; - } - - result = device->CreateVertexShader( - (DWORD*)vertexShaderBuffer->GetBufferPointer(), &VertexShader); - if (FAILED(result)) return; - - // Pixel shader - std::string fragShaderPath = - fmt::format("{}/{}{}", ShaderPath, name, FragShaderExtension); - source = (char*)SDL_LoadFile(fragShaderPath.c_str(), &sourceRawSz); - if (!source) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to read shader source file\n"); - return; - } - result = D3DCompile(source, sourceRawSz, nullptr, macros, nullptr, "main", - "ps_3_0", 0, 0, &pixelShaderBuffer, &errorBlob); - if (FAILED(result)) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to compile shader source file {:s}\n", - static_cast(errorBlob->GetBufferPointer())); - return; - } - - result = device->CreatePixelShader( - (DWORD*)pixelShaderBuffer->GetBufferPointer(), &PixelShader); - if (FAILED(result)) return; - - vertexShaderBuffer->Release(); - pixelShaderBuffer->Release(); - if (errorBlob) errorBlob->Release(); -} - -void Shader::UseShader(IDirect3DDevice9* device) { - device->SetVertexDeclaration(VertexDeclaration); - device->SetVertexShader(VertexShader); - device->SetPixelShader(PixelShader); -} - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/shader.h b/src/renderer/dx9/shader.h deleted file mode 100644 index 7ae96a203..000000000 --- a/src/renderer/dx9/shader.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include - -namespace Impacto { -namespace DirectX9 { - -class Shader { - public: - void Compile(char const* name, IDirect3DDevice9* device, - IDirect3DVertexDeclaration9* vertexDeclaration, - D3D_SHADER_MACRO* macros = nullptr); - void UseShader(IDirect3DDevice9* device); - - private: - IDirect3DVertexDeclaration9* VertexDeclaration; - - IDirect3DVertexShader9* VertexShader; - IDirect3DPixelShader9* PixelShader; -}; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/utils.h b/src/renderer/dx9/utils.h deleted file mode 100644 index c4894f73a..000000000 --- a/src/renderer/dx9/utils.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace Impacto { -namespace DirectX9 { - -inline ankerl::unordered_dense::map Textures; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/window.cpp b/src/renderer/dx9/window.cpp deleted file mode 100644 index 3a9b5a249..000000000 --- a/src/renderer/dx9/window.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "window.h" - -#include "../renderer.h" - -#include "../../log.h" - -#include "../../profile/game.h" -#include "../../profile/profile.h" -#include "../../userconfig.h" - -#include "../../game.h" - -#ifndef IMPACTO_DISABLE_IMGUI -#include -#endif - -namespace Impacto { -namespace DirectX9 { - -void DirectX9Window::UpdateDimensions() { - WindowDimensionsChanged = false; - // SDL_Vulkan_GetDrawableSize(SDLWindow, &WindowWidth, &WindowHeight); - if (WindowWidth != lastWidth || WindowHeight != lastHeight || - MsaaCount != lastMsaa || RenderScale != lastRenderScale) { - WindowDimensionsChanged = true; - ImpLog(LogLevel::Debug, LogChannel::General, - "Drawable size (pixels): {:d} x {:d} ({:d}x MSAA requested, render " - "scale " - "{:f})\n", - WindowWidth, WindowHeight, MsaaCount, RenderScale); - } - lastWidth = WindowWidth; - lastHeight = WindowHeight; - lastMsaa = MsaaCount; - lastRenderScale = RenderScale; - - DpiScale = SDL_GetWindowDisplayScale(SDLWindow); - // SDL_SetWindowInputFocus(SDLWindow); -} - -void DirectX9Window::Init() { - assert(IsInit == false); - ImpLog(LogLevel::Info, LogChannel::General, "Creating window\n"); - IsInit = true; - -#ifdef __ANDROID__ - SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); -#endif - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "SDL initialisation failed: {:s}\n", SDL_GetError()); - Shutdown(); - return; - } - - SDL_WindowFlags windowFlags = 0; - CreateSDLWindow(windowFlags); -} - -void DirectX9Window::SetDimensions(int width, int height, int msaa, - float renderScale) {} - -void DirectX9Window::SwapRTs() {} - -void DirectX9Window::Update() {} - -void DirectX9Window::Draw() { -#ifndef IMPACTO_DISABLE_IMGUI - if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } -#endif -} - -void DirectX9Window::Shutdown() { - SDL_DestroyWindow(SDLWindow); - SDL_Quit(); - // TODO move exit to users - exit(0); -} - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/window.h b/src/renderer/dx9/window.h deleted file mode 100644 index 4f78cfbf8..000000000 --- a/src/renderer/dx9/window.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "../window.h" - -namespace Impacto { -namespace DirectX9 { - -class DirectX9Window : public BaseWindow { - public: - void Init() override; - void SetDimensions(int width, int height, int msaa, - float renderScale) override; - void SwapRTs() override; - void Update() override; - void Draw() override; - void Shutdown() override; - - private: - void UpdateDimensions() override; -}; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/yuvframe.cpp b/src/renderer/dx9/yuvframe.cpp deleted file mode 100644 index 9b4360894..000000000 --- a/src/renderer/dx9/yuvframe.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "yuvframe.h" - -#include "../../log.h" - -namespace Impacto { -namespace DirectX9 { - -DX9YUVFrame::DX9YUVFrame(IDirect3DDevice9* device) { Device = device; } - -void DX9YUVFrame::Init(float width, float height) { - Width = width; - Height = height; - D3DFORMAT imageFormat = D3DFMT_A8; - auto err = Device->CreateTexture((UINT)Width, (UINT)Height, 1, 0, imageFormat, - D3DPOOL_MANAGED, &Luma, nullptr); - err = Device->CreateTexture((UINT)(Width / 2), (UINT)(Height / 2), 1, 0, - imageFormat, D3DPOOL_MANAGED, &Cb, nullptr); - err = Device->CreateTexture((UINT)(Width / 2), (UINT)(Height / 2), 1, 0, - imageFormat, D3DPOOL_MANAGED, &Cr, nullptr); -} - -void DX9YUVFrame::Submit(const void* luma, const void* cb, const void* cr) { - D3DLOCKED_RECT lockRect; - auto err = Luma->LockRect(0, &lockRect, NULL, 0); - memcpy(lockRect.pBits, luma, (size_t)(Width * Height)); - err = Luma->UnlockRect(0); - - err = Cb->LockRect(0, &lockRect, NULL, 0); - memcpy(lockRect.pBits, cb, (size_t)((Width / 2) * (Height / 2))); - err = Cb->UnlockRect(0); - - err = Cr->LockRect(0, &lockRect, NULL, 0); - memcpy(lockRect.pBits, cr, (size_t)((Width / 2) * (Height / 2))); - err = Cr->UnlockRect(0); -} - -void DX9YUVFrame::Release() { - Luma->Release(); - Cb->Release(); - Cr->Release(); -} - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/dx9/yuvframe.h b/src/renderer/dx9/yuvframe.h deleted file mode 100644 index 96d6cabac..000000000 --- a/src/renderer/dx9/yuvframe.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "../yuvframe.h" - -#include - -namespace Impacto { -namespace DirectX9 { - -class DX9YUVFrame : public YUVFrame { - friend class Renderer; - - public: - DX9YUVFrame(IDirect3DDevice9* device); - - void Init(float width, float height) override; - - void Submit(const void* luma, const void* cb, const void* cr) override; - void Release() override; - - protected: - IDirect3DDevice9* Device; - - IDirect3DTexture9* Luma; - IDirect3DTexture9* Cb; - IDirect3DTexture9* Cr; -}; - -} // namespace DirectX9 -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 6c1927571..39816bbbf 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -7,12 +7,6 @@ #ifndef IMPACTO_DISABLE_OPENGL #include "opengl/renderer.h" #endif -#ifndef IMPACTO_DISABLE_VULKAN -#include "vulkan/renderer.h" -#endif -#ifndef IMPACTO_DISABLE_DX9 -#include "dx9/renderer.h" -#endif #include @@ -24,16 +18,6 @@ void CreateRenderer() { case RendererType::OpenGL: Renderer = new OpenGL::Renderer(); break; -#endif -#ifndef IMPACTO_DISABLE_VULKAN - case RendererType::Vulkan: - Renderer = new Vulkan::Renderer(); - break; -#endif -#ifndef IMPACTO_DISABLE_DX9 - case RendererType::DirectX9: - Renderer = new DirectX9::Renderer(); - break; #endif default: ImpLog(LogLevel::Error, LogChannel::Render, diff --git a/src/renderer/vulkan/3d/renderable3d.cpp b/src/renderer/vulkan/3d/renderable3d.cpp deleted file mode 100644 index b46199126..000000000 --- a/src/renderer/vulkan/3d/renderable3d.cpp +++ /dev/null @@ -1,1154 +0,0 @@ -#include -#include - -#include "renderable3d.h" - -#include "../../3d/camera.h" -#include "../../3d/modelanimator.h" -#include "../../../log.h" -#include "../../../profile/scene3d.h" - -namespace Impacto { -namespace Vulkan { - -static uint32_t TextureDummy = 0; - -// character -static Pipeline *PipelineMain = 0, *PipelineOutline = 0, *PipelineEye = 0; -static Pipeline *PipelineMainNoDepthWrite = 0, *PipelineEyeNoDepthWrite = 0; - -// background -static Pipeline* PipelineBackground = 0; - -static AllocatedBuffer SceneUniformBuffers[MAX_FRAMES_IN_FLIGHT]; -static uint8_t* SceneUniformBuffersMapped[MAX_FRAMES_IN_FLIGHT]; - -static glm::mat4 ViewProjection; - -static bool IsInit = false; - -static MaterialType CurrentMaterial = MT_None; -static bool CurrentMaterialIsDepthWrite = false; - -static VulkanWindow* Window; -static VkDevice Device; -static VkCommandBuffer* CommandBuffers; -static VkDescriptorSetLayout ModelDescriptorSetLayout; -static VkDescriptorSetLayout BgTextureSetLayout; - -static uint32_t StagingBufferSize = 4096 * 4096; - -void Renderable3D::Init(VulkanWindow* window, VkDevice device, - VkRenderPass renderPass, - VkCommandBuffer* commandBuffers) { - assert(IsInit == false); - ImpLog(LogLevel::Info, LogChannel::Renderable3D, - "Initializing Renderable3D system\n"); - IsInit = true; - - Window = window; - Device = device; - CommandBuffers = commandBuffers; - - // Character shaders - VkDescriptorSetLayoutBinding uniformBinds[4] = {}; - uniformBinds[0].binding = 0; - uniformBinds[0].descriptorCount = 1; - uniformBinds[0].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; // Scene uniform - uniformBinds[0].pImmutableSamplers = nullptr; - uniformBinds[0].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; - uniformBinds[1].binding = 1; - uniformBinds[1].descriptorCount = 1; - uniformBinds[1].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; // Model uniform - uniformBinds[1].pImmutableSamplers = nullptr; - uniformBinds[1].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; - uniformBinds[2].binding = 2; - uniformBinds[2].descriptorCount = 1; - uniformBinds[2].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; // Mesh uniform - uniformBinds[2].pImmutableSamplers = nullptr; - uniformBinds[2].stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; - uniformBinds[3].binding = 3; - uniformBinds[3].descriptorCount = 4; - uniformBinds[3].descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; // Textures - uniformBinds[3].pImmutableSamplers = nullptr; - uniformBinds[3].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutCreateInfo modelSetLayoutInfo = {}; - modelSetLayoutInfo.bindingCount = 4; - modelSetLayoutInfo.flags = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - modelSetLayoutInfo.pNext = nullptr; - modelSetLayoutInfo.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - modelSetLayoutInfo.pBindings = uniformBinds; - - vkCreateDescriptorSetLayout(Device, &modelSetLayoutInfo, nullptr, - &ModelDescriptorSetLayout); - - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - SceneUniformBuffers[i] = CreateBuffer(sizeof(SceneUniformBufferType), - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - void* data; - vmaMapMemory(Allocator, SceneUniformBuffers[i].Allocation, &data); - SceneUniformBuffersMapped[i] = (uint8_t*)data; - } - - VkVertexInputBindingDescription modelBindingDescription{}; - modelBindingDescription.binding = 0; - modelBindingDescription.stride = Profile::Scene3D::Version == LKMVersion::DaSH - ? sizeof(VertexBufferDaSH) - : sizeof(VertexBuffer); - modelBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - VkVertexInputAttributeDescription modelAttributeDescriptions[5] = {}; - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - modelAttributeDescriptions[0].binding = 0; - modelAttributeDescriptions[0].location = 0; - modelAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - modelAttributeDescriptions[0].offset = offsetof(VertexBufferDaSH, Position); - modelAttributeDescriptions[1].binding = 0; - modelAttributeDescriptions[1].location = 1; - modelAttributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; - modelAttributeDescriptions[1].offset = offsetof(VertexBufferDaSH, Normal); - modelAttributeDescriptions[2].binding = 0; - modelAttributeDescriptions[2].location = 2; - modelAttributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; - modelAttributeDescriptions[2].offset = offsetof(VertexBufferDaSH, UV); - modelAttributeDescriptions[3].binding = 0; - modelAttributeDescriptions[3].location = 3; - modelAttributeDescriptions[3].format = VK_FORMAT_R8G8B8A8_SINT; - modelAttributeDescriptions[3].offset = - offsetof(VertexBufferDaSH, BoneIndices); - modelAttributeDescriptions[4].binding = 0; - modelAttributeDescriptions[4].location = 4; - modelAttributeDescriptions[4].format = VK_FORMAT_R32G32B32A32_SFLOAT; - modelAttributeDescriptions[4].offset = - offsetof(VertexBufferDaSH, BoneWeights); - - } else { - modelAttributeDescriptions[0].binding = 0; - modelAttributeDescriptions[0].location = 0; - modelAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - modelAttributeDescriptions[0].offset = offsetof(VertexBuffer, Position); - modelAttributeDescriptions[1].binding = 0; - modelAttributeDescriptions[1].location = 1; - modelAttributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; - modelAttributeDescriptions[1].offset = offsetof(VertexBuffer, Normal); - modelAttributeDescriptions[2].binding = 0; - modelAttributeDescriptions[2].location = 2; - modelAttributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; - modelAttributeDescriptions[2].offset = offsetof(VertexBuffer, UV); - modelAttributeDescriptions[3].binding = 0; - modelAttributeDescriptions[3].location = 3; - modelAttributeDescriptions[3].format = VK_FORMAT_R8G8B8A8_SINT; - modelAttributeDescriptions[3].offset = offsetof(VertexBuffer, BoneIndices); - modelAttributeDescriptions[4].binding = 0; - modelAttributeDescriptions[4].location = 4; - modelAttributeDescriptions[4].format = VK_FORMAT_R32G32B32A32_SFLOAT; - modelAttributeDescriptions[4].offset = offsetof(VertexBuffer, BoneWeights); - } - - VkPipelineDepthStencilStateCreateInfo depthStencil{}; - depthStencil.sType = - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencil.depthTestEnable = VK_TRUE; - depthStencil.depthWriteEnable = VK_TRUE; - depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; - depthStencil.depthBoundsTestEnable = VK_FALSE; - depthStencil.stencilTestEnable = VK_FALSE; - - VkPipelineRasterizationStateCreateInfo rasterizer{}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT; - rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - - VkPushConstantRange pushConstant; - pushConstant.offset = 0; - pushConstant.size = sizeof(PipelinePushConstants); - pushConstant.stageFlags = - VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT; - - PipelineMain = new Pipeline(Device, renderPass); - PipelineMain->SetPushConstants(&pushConstant, 1); - PipelineMain->SetDepthStencilInfo(depthStencil); - PipelineMain->CreateWithShader( - "Renderable3D_Character", modelBindingDescription, - modelAttributeDescriptions, 5, ModelDescriptorSetLayout); - - PipelineEye = new Pipeline(Device, renderPass); - PipelineEye->SetPushConstants(&pushConstant, 1); - PipelineEye->SetDepthStencilInfo(depthStencil); - PipelineEye->CreateWithShader("Renderable3D_Eye", modelBindingDescription, - modelAttributeDescriptions, 5, - ModelDescriptorSetLayout); - - depthStencil.depthWriteEnable = VK_FALSE; - PipelineOutline = new Pipeline(Device, renderPass); - PipelineOutline->SetPushConstants(&pushConstant, 1); - PipelineOutline->SetDepthStencilInfo(depthStencil); - PipelineOutline->SetRasterizerInfo(rasterizer); - PipelineOutline->CreateWithShader( - "Renderable3D_Outline", modelBindingDescription, - modelAttributeDescriptions, 5, ModelDescriptorSetLayout); - - PipelineMainNoDepthWrite = new Pipeline(Device, renderPass); - PipelineMainNoDepthWrite->SetPushConstants(&pushConstant, 1); - PipelineMainNoDepthWrite->SetDepthStencilInfo(depthStencil); - PipelineMainNoDepthWrite->CreateWithShader( - "Renderable3D_Character", modelBindingDescription, - modelAttributeDescriptions, 5, ModelDescriptorSetLayout); - - PipelineEyeNoDepthWrite = new Pipeline(Device, renderPass); - PipelineEyeNoDepthWrite->SetPushConstants(&pushConstant, 1); - PipelineEyeNoDepthWrite->SetDepthStencilInfo(depthStencil); - PipelineEyeNoDepthWrite->CreateWithShader( - "Renderable3D_Eye", modelBindingDescription, modelAttributeDescriptions, - 5, ModelDescriptorSetLayout); - - // BG shaders - VkDescriptorSetLayoutBinding bgBinds[2] = {}; - bgBinds[0].binding = 0; - bgBinds[0].descriptorCount = 1; - bgBinds[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; // MVP uniform - bgBinds[0].pImmutableSamplers = nullptr; - bgBinds[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - bgBinds[1].binding = 3; - bgBinds[1].descriptorCount = 1; - bgBinds[1].descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; // texture - bgBinds[1].pImmutableSamplers = nullptr; - bgBinds[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutCreateInfo bgBindInfo = {}; - bgBindInfo.bindingCount = 2; - bgBindInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - bgBindInfo.pNext = nullptr; - bgBindInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - bgBindInfo.pBindings = bgBinds; - - vkCreateDescriptorSetLayout(Device, &bgBindInfo, nullptr, - &BgTextureSetLayout); - - VkVertexInputBindingDescription backgroundBindingDescription{}; - backgroundBindingDescription.binding = 0; - backgroundBindingDescription.stride = sizeof(BgVertexBuffer); - backgroundBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - VkVertexInputAttributeDescription backgroundAttributeDescriptions[2] = {}; - backgroundAttributeDescriptions[0].binding = 0; - backgroundAttributeDescriptions[0].location = 0; - backgroundAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - backgroundAttributeDescriptions[0].offset = - offsetof(BgVertexBuffer, Position); - backgroundAttributeDescriptions[1].binding = 0; - backgroundAttributeDescriptions[1].location = 1; - backgroundAttributeDescriptions[1].format = VK_FORMAT_R32G32_SFLOAT; - backgroundAttributeDescriptions[1].offset = offsetof(BgVertexBuffer, UV); - PipelineBackground = new Pipeline(Device, renderPass); - PipelineBackground->SetPushConstants(&pushConstant, 1); - PipelineBackground->CreateWithShader( - "Renderable3D_Background", backgroundBindingDescription, - backgroundAttributeDescriptions, 2, BgTextureSetLayout); - - Texture texDummy; - texDummy.Load1x1(); - TextureDummy = texDummy.Submit(); -} - -void Renderable3D::BeginFrame(IScene3D* scene, Camera* camera) { - CurrentMaterial = MT_None; - - SceneUniformBufferType entry{}; - entry.ViewProjection = camera->ViewProjection; - entry.Tint = scene->Tint; - entry.WorldLightPosition = scene->LightPosition; - entry.WorldEyePosition = camera->CameraTransform.Position; - entry.DarkMode = scene->DarkMode; - memcpy(SceneUniformBuffersMapped[CurrentFrameIndex], &entry, - sizeof(SceneUniformBufferType)); - - ViewProjection = camera->ViewProjection; -} - -bool Renderable3D::LoadSync(uint32_t modelId) { - assert(IsUsed == false); - - ImpLog(LogLevel::Info, LogChannel::Renderable3D, - "Creating renderable (model ID {:d})\n", modelId); - - StaticModel = Model::Load(modelId); - ModelTransform = Transform(); - PrevPoseWeight = 0.0f; - - if (!StaticModel) { - ImpLog(LogLevel::Error, LogChannel::Renderable3D, - "Model loading failed for character with model ID {:d}\n", modelId); - return false; - } - - InitMeshAnimStatus(); - ReloadDefaultBoneTransforms(); - - Animator.Character = this; - SwitchAnimation(StaticModel->IdleAnimation, 0.0f); - - IsUsed = true; - - return true; -} - -void Renderable3D::MakePlane() { - assert(IsUsed == false); - - StaticModel = Model::MakePlane(); - ModelTransform = Transform(); - PrevPoseWeight = 0.0f; - - Animator.Character = this; - - InitMeshAnimStatus(); - ReloadDefaultBoneTransforms(); - - IsUsed = true; -} - -void Renderable3D::InitMeshAnimStatus() { - int totalMorphedVertices = 0; - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - MeshAnimStatus[i].MorphedVerticesOffset = totalMorphedVertices; - if (StaticModel->Meshes[i].MorphTargetCount > 0) { - totalMorphedVertices += StaticModel->Meshes[i].VertexCount; - } - } - if (totalMorphedVertices > 0) { - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - CurrentMorphedVerticesVk[i] = CreateBuffer( - totalMorphedVertices * sizeof(VertexBufferDaSH), - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - } else { - CurrentMorphedVerticesVk[i] = CreateBuffer( - totalMorphedVertices * sizeof(VertexBuffer), - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - } - vmaMapMemory(Allocator, CurrentMorphedVerticesVk[i].Allocation, - &CurrentMorphedVerticesVkMapped[i]); - } - } - ReloadDefaultMeshAnimStatus(); -} - -void Renderable3D::ReloadDefaultMeshAnimStatus() { - /* - void* currentMorphedVertex; - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertex = - ((VertexBufferDaSH*)CurrentMorphedVerticesVkMapped[CurrentFrameIndex]); - } else { - currentMorphedVertex = - ((VertexBuffer*)CurrentMorphedVerticesVkMapped[CurrentFrameIndex]); - } - VertexBuffer* currentMorphedVertexRNE = - (VertexBuffer*)currentMorphedVertex; VertexBufferDaSH* - currentMorphedVertexDaSH = - (VertexBufferDaSH*)currentMorphedVertex; - */ - - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - MeshAnimStatus[i].Visible = 1.0f; - if (StaticModel->Meshes[i].MorphTargetCount > 0) { - for (int j = 0; j < StaticModel->Meshes[i].MorphTargetCount; j++) { - MeshAnimStatus[i].MorphInfluences[j] = 0.0f; - } - } - } -} - -void Renderable3D::SwitchAnimation(int16_t animId, float transitionTime) { - if (Animator.CurrentAnimation != 0 && transitionTime > 0.0f) { - PrevPoseWeight = 1.0f; - for (uint32_t i = 0; i < StaticModel->BoneCount; i++) { - PrevBoneTransforms[i] = CurrentPose[i].LocalTransform; - } - memcpy(PrevMeshAnimStatus, MeshAnimStatus, sizeof(MeshAnimStatus)); - AnimationTransitionTime = transitionTime; - } else { - PrevPoseWeight = 0.0f; - } - Animator.Start(animId); -} - -void Renderable3D::ReloadDefaultBoneTransforms() { - for (uint32_t i = 0; i < StaticModel->BoneCount; i++) { - CurrentPose[i].LocalTransform = StaticModel->Bones[i].BaseTransform; - } -} - -void Renderable3D::CalculateMorphedVertices(int id) { - Mesh* mesh = &StaticModel->Meshes[id]; - AnimatedMesh* animStatus = &MeshAnimStatus[id]; - AnimatedMesh* prevAnimStatus = &PrevMeshAnimStatus[id]; - if (mesh->MorphTargetCount == 0) return; - - void* currentMorphedVertex; - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertex = - ((VertexBufferDaSH*)CurrentMorphedVerticesVkMapped[CurrentFrameIndex]) + - animStatus->MorphedVerticesOffset; - } else { - currentMorphedVertex = - ((VertexBuffer*)CurrentMorphedVerticesVkMapped[CurrentFrameIndex]) + - animStatus->MorphedVerticesOffset; - } - VertexBuffer* currentMorphedVertexRNE = (VertexBuffer*)currentMorphedVertex; - VertexBufferDaSH* currentMorphedVertexDaSH = - (VertexBufferDaSH*)currentMorphedVertex; - - void* currentVertex; - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentVertex = - ((VertexBufferDaSH*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } else { - currentVertex = - ((VertexBuffer*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } - - VertexBuffer* currentVertexRNE = (VertexBuffer*)currentVertex; - VertexBufferDaSH* currentVertexDaSH = (VertexBufferDaSH*)currentVertex; - - for (uint32_t j = 0; j < mesh->VertexCount; j++) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - memcpy(currentMorphedVertexDaSH, currentVertexDaSH, - sizeof(VertexBufferDaSH)); - currentMorphedVertexDaSH++; - currentVertexDaSH++; - } else { - memcpy(currentMorphedVertexRNE, currentVertexRNE, sizeof(VertexBuffer)); - currentMorphedVertexRNE++; - currentVertexRNE++; - } - } - - for (int k = 0; k < mesh->MorphTargetCount; k++) { - float influence; - if (PrevPoseWeight > 0.0f) { - influence = glm::mix(prevAnimStatus->MorphInfluences[k], - animStatus->MorphInfluences[k], - glm::smoothstep(0.0f, 1.0f, 1.0f - PrevPoseWeight)); - } else { - influence = animStatus->MorphInfluences[k]; - } - - if (influence == 0.0f) continue; - - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertex = - ((VertexBufferDaSH*) - CurrentMorphedVerticesVkMapped[CurrentFrameIndex]) + - animStatus->MorphedVerticesOffset; - } else { - currentMorphedVertex = - ((VertexBuffer*)CurrentMorphedVerticesVkMapped[CurrentFrameIndex]) + - animStatus->MorphedVerticesOffset; - } - currentMorphedVertexRNE = (VertexBuffer*)currentMorphedVertex; - currentMorphedVertexDaSH = (VertexBufferDaSH*)currentMorphedVertex; - - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentVertex = - ((VertexBufferDaSH*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } else { - currentVertex = - ((VertexBuffer*)StaticModel->VertexBuffers) + mesh->VertexOffset; - } - - currentVertexRNE = (VertexBuffer*)currentVertex; - currentVertexDaSH = (VertexBufferDaSH*)currentVertex; - - MorphVertexBuffer* currentMorphTargetVbo = - StaticModel->MorphVertexBuffers + - StaticModel->MorphTargets[mesh->MorphTargetIds[k]].VertexOffset; - - for (uint32_t j = 0; j < mesh->VertexCount; j++) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - currentMorphedVertexDaSH->Position += - (currentMorphTargetVbo->Position - currentVertexDaSH->Position) * - influence; - currentMorphedVertexDaSH->Normal += - (currentMorphTargetVbo->Normal - currentVertexDaSH->Normal) * - influence; - currentVertexDaSH++; - currentMorphedVertexDaSH++; - } else { - currentMorphedVertexRNE->Position += - (currentMorphTargetVbo->Position - currentVertexRNE->Position) * - influence; - currentMorphedVertexRNE->Normal += - (currentMorphTargetVbo->Normal - currentVertexRNE->Normal) * - influence; - currentVertexRNE++; - currentMorphedVertexRNE++; - } - currentMorphTargetVbo++; - } - } -} - -void Renderable3D::Pose() { - for (int i = 0; i < StaticModel->RootBoneCount; i++) { - PoseBone(StaticModel->RootBones[i]); - } -} - -void Renderable3D::PoseBone(int16_t id) { - StaticBone* bone = &StaticModel->Bones[id]; - PosedBone* transformed = &CurrentPose[id]; - - glm::mat4 parentWorld; - if (bone->Parent < 0) { - parentWorld = glm::mat4(1.0); - } else { - parentWorld = CurrentPose[bone->Parent].World; - } - - Transform transform; - if (PrevPoseWeight > 0.0f) { - transform = PrevBoneTransforms[id].Interpolate( - transformed->LocalTransform, - glm::smoothstep(0.0f, 1.0f, 1.0f - PrevPoseWeight)); - } else { - transform = transformed->LocalTransform; - } - - glm::mat4 local = transform.Matrix(); - - transformed->World = parentWorld * local; - - for (int i = 0; i < bone->ChildrenCount; i++) { - PoseBone(bone->Children[i]); - } - - transformed->Offset = transformed->World * bone->BindInverse; -} - -void Renderable3D::Update(float dt) { - if (!IsUsed) return; - if (Animator.CurrentAnimation) { - if (!Animator.IsPlaying) { - // oneshot ended - SwitchAnimation(StaticModel->IdleAnimation, AnimationTransitionTime); - } else { - Animator.Update(dt); - } - } - Pose(); - if (PrevPoseWeight > 0.0f) { - PrevPoseWeight -= dt / AnimationTransitionTime; - if (PrevPoseWeight < 0.0f) PrevPoseWeight = 0.0f; - } - - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - CalculateMorphedVertices(i); - } -} - -void Renderable3D::DrawMesh(int id, RenderPass pass) { - if (pass == RP_Outline && StaticModel->Type == ModelType_Background) return; - - if (!MeshAnimStatus[id].Visible) return; - - Mesh& mesh = StaticModel->Meshes[id]; - - if (pass == RP_First && mesh.Flags & MeshFlag_Later) return; - if (pass == RP_Second && !(mesh.Flags & MeshFlag_Later)) return; - - if (pass == RP_Outline) { - UseMaterial(MT_Outline); - } else { - UseMaterial(mesh.Material); - } - // Because of the above, we use CurrentMaterial later, not mesh.Material - - UseMesh(id); - - VkDescriptorBufferInfo bgMvpBufferInfo{}; - VkDescriptorBufferInfo sceneBufferInfo{}; - VkDescriptorBufferInfo modelBufferInfo{}; - VkDescriptorBufferInfo meshBufferInfo{}; - switch (CurrentMaterial) { - case MT_Background: { - bgMvpBufferInfo.buffer = - BackgroundMvpBuffers[id][CurrentFrameIndex].Buffer; - bgMvpBufferInfo.offset = 0; - bgMvpBufferInfo.range = sizeof(BgMVPUniformBufferType); - - WriteDescriptorSet[CurrentWriteDescriptorSet].sType = - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstSet = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstBinding = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorCount = 1; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - WriteDescriptorSet[CurrentWriteDescriptorSet].pBufferInfo = - &bgMvpBufferInfo; - CurrentWriteDescriptorSet += 1; - } break; - case MT_Generic: - case MT_Eye: - case MT_Outline: - case MT_DaSH_Generic: - case MT_DaSH_Face: - case MT_DaSH_Skin: - case MT_DaSH_Eye: { - sceneBufferInfo.buffer = SceneUniformBuffers[CurrentFrameIndex].Buffer; - sceneBufferInfo.offset = 0; - sceneBufferInfo.range = sizeof(SceneUniformBufferType); - - WriteDescriptorSet[CurrentWriteDescriptorSet].sType = - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstSet = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstBinding = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorCount = 1; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - WriteDescriptorSet[CurrentWriteDescriptorSet].pBufferInfo = - &sceneBufferInfo; - CurrentWriteDescriptorSet += 1; - - modelBufferInfo.buffer = ModelUniformBuffers[CurrentFrameIndex].Buffer; - modelBufferInfo.offset = 0; - modelBufferInfo.range = sizeof(ModelUniformBufferType); - - WriteDescriptorSet[CurrentWriteDescriptorSet].sType = - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstSet = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstBinding = 1; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorCount = 1; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - WriteDescriptorSet[CurrentWriteDescriptorSet].pBufferInfo = - &modelBufferInfo; - CurrentWriteDescriptorSet += 1; - - meshBufferInfo.buffer = MeshUniformBuffers[id][CurrentFrameIndex].Buffer; - meshBufferInfo.offset = 0; - meshBufferInfo.range = sizeof(MeshUniformBufferType); - - WriteDescriptorSet[CurrentWriteDescriptorSet].sType = - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstSet = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstBinding = 2; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorCount = 1; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorType = - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - WriteDescriptorSet[CurrentWriteDescriptorSet].pBufferInfo = - &meshBufferInfo; - CurrentWriteDescriptorSet += 1; - - } break; - default: - ImpLog(LogLevel::Warning, LogChannel::Renderable3D, - "Unknown material!\n"); - break; - } - - int textureCount = 0; - - switch (CurrentMaterial) { - case MT_Background: { - int constexpr backgroundTextureTypes[] = {TT_ColorMap}; - textureCount = 1; - SetTextures(id, backgroundTextureTypes, 1); - break; - } - case MT_Outline: { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - int constexpr outlineTextureTypes[] = {TT_DaSH_ColorMap, - TT_DaSH_NoiseMap}; - textureCount = 2; - SetTextures(id, outlineTextureTypes, 2); - } else { - int constexpr outlineTextureTypes[] = {TT_ColorMap}; - textureCount = 1; - SetTextures(id, outlineTextureTypes, 1); - } - break; - } - case MT_Generic: { - int constexpr genericTextureTypes[] = {TT_ColorMap, TT_GradientMaskMap, - TT_SpecularColorMap}; - textureCount = 3; - SetTextures(id, genericTextureTypes, 3); - break; - } - case MT_Eye: { - int constexpr eyeTextureTypes[] = { - TT_Eye_IrisColorMap, TT_Eye_WhiteColorMap, TT_Eye_HighlightColorMap, - TT_Eye_IrisSpecularColorMap}; - textureCount = 4; - SetTextures(id, eyeTextureTypes, 4); - break; - } - case MT_DaSH_Generic: { - int constexpr dashGenericTextureTypes[] = { - TT_DaSH_ColorMap, TT_DaSH_GradientMaskMap, TT_DaSH_SpecularColorMap, - TT_DaSH_ShadowColorMap}; - textureCount = 4; - SetTextures(id, dashGenericTextureTypes, 4); - break; - } - case MT_DaSH_Face: - case MT_DaSH_Skin: { - int constexpr dashGenericTextureTypes[] = { - TT_DaSH_ColorMap, TT_DaSH_GradientMaskMap, TT_DaSH_SpecularColorMap}; - textureCount = 3; - SetTextures(id, dashGenericTextureTypes, 3); - break; - } - case MT_DaSH_Eye: { - int constexpr dashEyeTextureTypes[] = {TT_DaSH_Eye_IrisColorMap, - TT_DaSH_Eye_WhiteColorMap, - TT_DaSH_Eye_HighlightColorMap}; - textureCount = 3; - SetTextures(id, dashEyeTextureTypes, 3); - break; - } - default: - ImpLog(LogLevel::Warning, LogChannel::Renderable3D, - "Unknown material!\n"); - break; - } - - CurrentTextureBufferInfo = 0; - - if (mesh.Opacity < 0.9 && CurrentMaterialIsDepthWrite) { - switch (CurrentMaterial) { - case MT_Generic: - case MT_DaSH_Generic: - case MT_DaSH_Face: - case MT_DaSH_Skin: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineMainNoDepthWrite->GraphicsPipeline); - CurrentPipeline = PipelineMainNoDepthWrite; - } break; - case MT_Eye: - case MT_DaSH_Eye: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineEyeNoDepthWrite->GraphicsPipeline); - CurrentPipeline = PipelineEyeNoDepthWrite; - break; - } - default: - ImpLog(LogLevel::Warning, LogChannel::Renderable3D, - "Unknown material!\n"); - break; - } - } - - WriteDescriptorSet[CurrentWriteDescriptorSet].sType = - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstSet = 0; - WriteDescriptorSet[CurrentWriteDescriptorSet].dstBinding = 3; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorCount = textureCount; - WriteDescriptorSet[CurrentWriteDescriptorSet].descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - WriteDescriptorSet[CurrentWriteDescriptorSet].pImageInfo = TextureBufferInfo; - CurrentWriteDescriptorSet += 1; - - vkCmdPushDescriptorSetKHR(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->PipelineLayout, 0, - CurrentWriteDescriptorSet, WriteDescriptorSet); - CurrentWriteDescriptorSet = 0; - - PipelinePushConstants pushConstants{Profile::Scene3D::Version == - LKMVersion::DaSH}; - vkCmdPushConstants(CommandBuffers[CurrentFrameIndex], - CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof(PipelinePushConstants), &pushConstants); - - if (StaticModel->Meshes[id].MorphTargetCount > 0) { - VkBuffer vertexBuffers[] = { - CurrentMorphedVerticesVk[CurrentFrameIndex].Buffer}; - size_t stride = Profile::Scene3D::Version == LKMVersion::DaSH - ? sizeof(VertexBufferDaSH) - : sizeof(VertexBuffer); - VkDeviceSize offsets[] = { - (VkDeviceSize)(MeshAnimStatus[id].MorphedVerticesOffset * stride)}; - vkCmdBindVertexBuffers(CommandBuffers[CurrentFrameIndex], 0, 1, - vertexBuffers, offsets); - } else { - VkBuffer vertexBuffers[] = { - MeshVertexBuffers[id][CurrentFrameIndex].Buffer}; - VkDeviceSize offsets[] = {(VkDeviceSize)0}; - vkCmdBindVertexBuffers(CommandBuffers[CurrentFrameIndex], 0, 1, - vertexBuffers, offsets); - } - vkCmdBindIndexBuffer(CommandBuffers[CurrentFrameIndex], - MeshIndexBuffers[id][CurrentFrameIndex].Buffer, 0, - VK_INDEX_TYPE_UINT16); - vkCmdDrawIndexed(CommandBuffers[CurrentFrameIndex], mesh.IndexCount, 1, 0, 0, - 0); - - if (mesh.Opacity < 0.9 && CurrentMaterialIsDepthWrite) { - switch (CurrentMaterial) { - case MT_Generic: - case MT_DaSH_Generic: - case MT_DaSH_Face: - case MT_DaSH_Skin: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineMain->GraphicsPipeline); - CurrentPipeline = PipelineMain; - } break; - case MT_Eye: - case MT_DaSH_Eye: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineEye->GraphicsPipeline); - CurrentPipeline = PipelineEye; - break; - } - default: - ImpLog(LogLevel::Warning, LogChannel::Renderable3D, - "Unknown material!\n"); - break; - } - } - - if (pass != RP_Outline) DrawMesh(id, RP_Outline); -} - -void Renderable3D::Render() { - if (!IsUsed || !IsVisible) return; - - LoadModelUniforms(); - - memset(UniformsUpdated, 0, sizeof(UniformsUpdated)); - CurrentTextureBufferInfo = 0; - CurrentWriteDescriptorSet = 0; - - for (int i = RP_First; i < RP_Count; i++) { - for (size_t j = 0; j < StaticModel->MeshCount; j++) { - DrawMesh((int)j, (RenderPass)i); - } - } - - if (CurrentMaterial == MT_Outline) { - // Clean up some state - UseMaterial(MT_Background); - } -} - -void Renderable3D::SetTextures(int id, int const* textureTypes, int count) { - for (int i = 0; i < count; i++) { - int t = textureTypes[i]; - if (StaticModel->Meshes[id].Maps[t] >= 0) { - TextureBufferInfo[CurrentTextureBufferInfo].sampler = Sampler; - TextureBufferInfo[CurrentTextureBufferInfo].imageView = - Textures[TexBuffers[StaticModel->Meshes[id].Maps[t]]].ImageView; - TextureBufferInfo[CurrentTextureBufferInfo].imageLayout = - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } else { - TextureBufferInfo[CurrentTextureBufferInfo].sampler = Sampler; - TextureBufferInfo[CurrentTextureBufferInfo].imageView = - Textures[TextureDummy].ImageView; - TextureBufferInfo[CurrentTextureBufferInfo].imageLayout = - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - CurrentTextureBufferInfo += 1; - } -} - -void Renderable3D::LoadModelUniforms() { - if (StaticModel->Type == ModelType_Character) { - ModelUniformBufferType entry{}; - entry.Model = ModelTransform.Matrix(); - memcpy(ModelUniformBuffersMapped[CurrentFrameIndex], &entry, - sizeof(ModelUniformBufferType)); - } -} - -void Renderable3D::UseMaterial(MaterialType type) { - if (CurrentMaterial == type) return; - - switch (type) { - case MT_Outline: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineOutline->GraphicsPipeline); - CurrentPipeline = PipelineOutline; - break; - } - case MT_Background: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineBackground->GraphicsPipeline); - CurrentPipeline = PipelineBackground; - break; - } - case MT_Generic: - case MT_DaSH_Generic: - case MT_DaSH_Face: - case MT_DaSH_Skin: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineMain->GraphicsPipeline); - CurrentPipeline = PipelineMain; - break; - } - case MT_Eye: - case MT_DaSH_Eye: { - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineEye->GraphicsPipeline); - CurrentPipeline = PipelineEye; - break; - } - default: - ImpLog(LogLevel::Warning, LogChannel::Renderable3D, - "Unknown material!\n"); - break; - } - - if (type == MT_Outline) { - CurrentMaterialIsDepthWrite = false; - } else { - CurrentMaterialIsDepthWrite = true; - } - - CurrentMaterial = type; -} - -void Renderable3D::UseMesh(int id) { LoadMeshUniforms(id); } - -void Renderable3D::LoadMeshUniforms(int id) { - Mesh& mesh = StaticModel->Meshes[id]; - - if (StaticModel->Type == ModelType_Character) { - MeshUniformBufferType entry{}; - if (!UniformsUpdated[id]) { - if (mesh.UsedBones > 0) { - glm::mat4* outBone = entry.Bones; - for (uint32_t j = 0; j < mesh.UsedBones; j++) { - *outBone = CurrentPose[mesh.BoneMap[j]].Offset; - outBone++; - } - } else { - entry.Bones[0] = CurrentPose[mesh.MeshBone].Offset; - } - - entry.ModelOpacity = mesh.Opacity; - entry.HasShadowColorMap = - mesh.Material == MT_DaSH_Generic && mesh.HasShadowColorMap; - - memcpy(MeshUniformBuffersMapped[id][CurrentFrameIndex], &entry, - sizeof(MeshUniformBufferType)); - - UniformsUpdated[id] = true; - } - } else if (StaticModel->Type == ModelType_Background) { - BgMVPUniformBufferType entry{}; - entry.MVP = ViewProjection * mesh.ModelTransform.Matrix(); - memcpy(BackgroundMvpMapped[id][CurrentFrameIndex], &entry, - sizeof(BgMVPUniformBufferType)); - } -} - -void Renderable3D::UnloadSync() { - Animator.CurrentAnimation = 0; - PrevPoseWeight = 0.0f; - if (StaticModel) { - ImpLog(LogLevel::Info, LogChannel::Renderable3D, "Unloading model {:d}\n", - StaticModel->Id); - if (IsSubmitted) { - if (StaticModel->Type == ModelType_Background) { - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - for (uint32_t j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) { - vmaUnmapMemory(Allocator, BackgroundMvpBuffers[i][j].Allocation); - vmaDestroyBuffer(Allocator, BackgroundMvpBuffers[i][j].Buffer, - BackgroundMvpBuffers[i][j].Allocation); - } - } - } else { - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - for (uint32_t j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) { - vmaUnmapMemory(Allocator, MeshUniformBuffers[i][j].Allocation); - vmaDestroyBuffer(Allocator, MeshUniformBuffers[i][j].Buffer, - MeshUniformBuffers[i][j].Allocation); - } - } - } - - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vmaUnmapMemory(Allocator, ModelUniformBuffers[i].Allocation); - vmaDestroyBuffer(Allocator, ModelUniformBuffers[i].Buffer, - ModelUniformBuffers[i].Allocation); - } - } - delete StaticModel; - StaticModel = 0; - } - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (CurrentMorphedVerticesVkMapped[i]) { - vmaUnmapMemory(Allocator, CurrentMorphedVerticesVk[i].Allocation); - CurrentMorphedVerticesVkMapped[i] = 0; - vmaDestroyBuffer(Allocator, CurrentMorphedVerticesVk[i].Buffer, - CurrentMorphedVerticesVk[i].Allocation); - } - } - if (CurrentMorphedVertices) { - free(CurrentMorphedVertices); - CurrentMorphedVertices = 0; - } - ModelTransform = Transform(); - IsSubmitted = false; - IsUsed = false; - IsVisible = false; -} - -void Renderable3D::MainThreadOnLoad() { - assert(IsSubmitted == false); - - ImpLog(LogLevel::Info, LogChannel::Renderable3D, - "Submitting data to GPU for model ID {:d}\n", StaticModel->Id); - - if (StaticModel->Type == ModelType_Background) { - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - for (uint32_t j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) { - BackgroundMvpBuffers[i][j] = CreateBuffer( - sizeof(BgMVPUniformBufferType), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - void* data; - vmaMapMemory(Allocator, BackgroundMvpBuffers[i][j].Allocation, &data); - BackgroundMvpMapped[i][j] = (uint8_t*)data; - } - } - } - - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - ModelUniformBuffers[i] = CreateBuffer(sizeof(ModelUniformBufferType), - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - void* data; - vmaMapMemory(Allocator, ModelUniformBuffers[i].Allocation, &data); - ModelUniformBuffersMapped[i] = (uint8_t*)data; - } - - auto stagingBuffer = - CreateBuffer(StagingBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - - void* stagingBufferMapped; - vmaMapMemory(Allocator, stagingBuffer.Allocation, &stagingBufferMapped); - - for (uint32_t i = 0; i < StaticModel->MeshCount; i++) { - for (uint32_t j = 0; j < MAX_FRAMES_IN_FLIGHT; j++) { - MeshUniformBuffers[i][j] = CreateBuffer( - sizeof(MeshUniformBufferType), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - void* data; - vmaMapMemory(Allocator, MeshUniformBuffers[i][j].Allocation, &data); - MeshUniformBuffersMapped[i][j] = (uint8_t*)data; - - uint32_t vertexCopySize = 0; - - if (StaticModel->Type == ModelType_Character) { - if (Profile::Scene3D::Version == LKMVersion::DaSH) { - MeshVertexBuffers[i][j] = CreateBuffer( - sizeof(VertexBufferDaSH) * StaticModel->Meshes[i].VertexCount, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - vertexCopySize = - sizeof(VertexBufferDaSH) * StaticModel->Meshes[i].VertexCount; - - memcpy(stagingBufferMapped, - (VertexBufferDaSH*)StaticModel->VertexBuffers + - StaticModel->Meshes[i].VertexOffset, - sizeof(VertexBufferDaSH) * StaticModel->Meshes[i].VertexCount); - } else { - MeshVertexBuffers[i][j] = CreateBuffer( - sizeof(VertexBuffer) * StaticModel->Meshes[i].VertexCount, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VMA_MEMORY_USAGE_GPU_ONLY); - vertexCopySize = - sizeof(VertexBuffer) * StaticModel->Meshes[i].VertexCount; - - memcpy(stagingBufferMapped, - (VertexBuffer*)StaticModel->VertexBuffers + - StaticModel->Meshes[i].VertexOffset, - sizeof(VertexBuffer) * StaticModel->Meshes[i].VertexCount); - } - } else if (StaticModel->Type == ModelType_Background) { - MeshVertexBuffers[i][j] = CreateBuffer( - sizeof(BgVertexBuffer) * StaticModel->Meshes[i].VertexCount, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VMA_MEMORY_USAGE_GPU_ONLY); - vertexCopySize = - sizeof(BgVertexBuffer) * StaticModel->Meshes[i].VertexCount; - - memcpy(stagingBufferMapped, - (BgVertexBuffer*)StaticModel->VertexBuffers + - StaticModel->Meshes[i].VertexOffset, - sizeof(BgVertexBuffer) * StaticModel->Meshes[i].VertexCount); - } - - MeshIndexBuffers[i][j] = CreateBuffer( - sizeof(uint16_t) * StaticModel->Meshes[i].IndexCount, - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VMA_MEMORY_USAGE_GPU_ONLY); - - memcpy((uint8_t*)stagingBufferMapped + vertexCopySize, - StaticModel->Indices + StaticModel->Meshes[i].IndexOffset, - sizeof(uint16_t) * StaticModel->Meshes[i].IndexCount); - - ImmediateSubmit( - [this, vertexCopySize, stagingBuffer, i, j](VkCommandBuffer cmd) { - VkBufferCopy copy; - copy.dstOffset = 0; - copy.srcOffset = 0; - copy.size = vertexCopySize; - vkCmdCopyBuffer(cmd, stagingBuffer.Buffer, - MeshVertexBuffers[i][j].Buffer, 1, ©); - - copy.dstOffset = 0; - copy.srcOffset = vertexCopySize; - copy.size = sizeof(uint16_t) * StaticModel->Meshes[i].IndexCount; - vkCmdCopyBuffer(cmd, stagingBuffer.Buffer, - MeshIndexBuffers[i][j].Buffer, 1, ©); - }); - } - } - - for (uint32_t i = 0; i < StaticModel->TextureCount; i++) { - TexBuffers[i] = StaticModel->Textures[i].Submit(); - if (TexBuffers[i] == 0) { - ImpLog(LogLevel::Fatal, LogChannel::Renderable3D, - "Submitting texture {:d} for model {:d} failed\n", i, - StaticModel->Id); - } - } - - vmaUnmapMemory(Allocator, stagingBuffer.Allocation); - vmaDestroyBuffer(Allocator, stagingBuffer.Buffer, stagingBuffer.Allocation); - - IsSubmitted = true; -} - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/3d/renderable3d.h b/src/renderer/vulkan/3d/renderable3d.h deleted file mode 100644 index 6b4be688d..000000000 --- a/src/renderer/vulkan/3d/renderable3d.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include "../utils.h" -#include "../pipeline.h" -#include "../window.h" -#include "../../3d/renderable3d.h" - -namespace Impacto { -namespace Vulkan { - -enum RenderPass { RP_Outline = 0, RP_First = 1, RP_Second = 2, RP_Count }; - -struct PipelinePushConstants { - VkBool32 IsDash; -}; - -struct SceneUniformBufferType { - alignas(16) glm::mat4 ViewProjection; - alignas(16) glm::vec4 Tint; - alignas(16) glm::vec3 WorldLightPosition; - alignas(16) glm::vec3 WorldEyePosition; - alignas(16) VkBool32 DarkMode; -}; - -struct ModelUniformBufferType { - alignas(16) glm::mat4 Model; -}; - -struct MeshUniformBufferType { - alignas(16) glm::mat4 Bones[ModelMaxBonesPerMesh]; - alignas(16) float ModelOpacity; - alignas(16) VkBool32 HasShadowColorMap; -}; - -struct BgMVPUniformBufferType { - alignas(16) glm::mat4 MVP; -}; - -class Renderable3D : public IRenderable3D { - public: - static void Init(VulkanWindow* window, VkDevice device, - VkRenderPass renderPass, VkCommandBuffer* commandBuffers); - static void BeginFrame(IScene3D* scene, Camera* camera); - - void MakePlane() override; - - void Update(float dt) override; - void Render() override; - - void ReloadDefaultBoneTransforms() override; - void InitMeshAnimStatus() override; - void ReloadDefaultMeshAnimStatus() override; - - void SwitchAnimation(int16_t animId, float transitionTime) override; - - protected: - bool LoadSync(uint32_t modelId) override; - void UnloadSync() override; - void MainThreadOnLoad() override; - - private: - void Pose(); - void PoseBone(int16_t id); - - void CalculateMorphedVertices(int id); - - void UseMaterial(MaterialType type); - void UseMesh(int id); - void LoadModelUniforms(); - void LoadMeshUniforms(int id); - void SetTextures(int id, int const* textureUnits, int count); - void DrawMesh(int id, RenderPass pass); - - AllocatedBuffer ModelUniformBuffers[MAX_FRAMES_IN_FLIGHT]; - uint8_t* ModelUniformBuffersMapped[MAX_FRAMES_IN_FLIGHT]; - AllocatedBuffer MeshUniformBuffers[ModelMaxMeshesPerModel] - [MAX_FRAMES_IN_FLIGHT]; - uint8_t* MeshUniformBuffersMapped[ModelMaxMeshesPerModel] - [MAX_FRAMES_IN_FLIGHT]; - AllocatedBuffer MeshVertexBuffers[ModelMaxMeshesPerModel] - [MAX_FRAMES_IN_FLIGHT]; - AllocatedBuffer MeshIndexBuffers[ModelMaxMeshesPerModel] - [MAX_FRAMES_IN_FLIGHT]; - - AllocatedBuffer BackgroundMvpBuffers[ModelMaxMeshesPerModel] - [MAX_FRAMES_IN_FLIGHT]; - uint8_t* BackgroundMvpMapped[ModelMaxMeshesPerModel][MAX_FRAMES_IN_FLIGHT]; - - int CurrentTextureBufferInfo = 0; - VkDescriptorImageInfo TextureBufferInfo[4]; - - int CurrentWriteDescriptorSet = 0; - VkWriteDescriptorSet WriteDescriptorSet[4]; - - AllocatedBuffer CurrentMorphedVerticesVk[MAX_FRAMES_IN_FLIGHT]; - void* CurrentMorphedVerticesVkMapped[MAX_FRAMES_IN_FLIGHT]; - - uint32_t TexBuffers[ModelMaxTexturesPerModel]; - - bool UniformsUpdated[ModelMaxMeshesPerModel]; - - Transform PrevBoneTransforms[ModelMaxBonesPerModel]; - AnimatedMesh PrevMeshAnimStatus[ModelMaxMeshesPerModel]; - float PrevPoseWeight; - float AnimationTransitionTime; -}; - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/3d/scene.cpp b/src/renderer/vulkan/3d/scene.cpp deleted file mode 100644 index 76b57e806..000000000 --- a/src/renderer/vulkan/3d/scene.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "scene.h" - -#include "../../3d/camera.h" -#include "../../../log.h" -#include "renderable3d.h" - -#include "../../../profile/scene3d.h" - -namespace Impacto { -namespace Vulkan { - -Scene3D::Scene3D(VulkanWindow* window, VkDevice device, VkRenderPass renderPass, - VkCommandBuffer* commandBuffers) { - Window = window; - Device = device; - RenderPass = renderPass; - CommandBuffers = commandBuffers; -} - -void Scene3D::Init() { - assert(IsInit == false); - ImpLog(LogLevel::Info, LogChannel::Scene, "Initializing 3D scene system\n"); - IsInit = true; - - Profile::Scene3D::Configure(); - - Renderables = new IRenderable3D*[Profile::Scene3D::MaxRenderables]; - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - Renderables[i] = new Renderable3D(); - } - - Renderable3D::Init(Window, Device, RenderPass, CommandBuffers); - - MainCamera.Init(); - - // clang-format off - float ScreenFillingTriangle[] = { - // Position // UV - -1.0f, -1.0f, 0.0f, 0.0f, - 3.0f, -1.0f, 2.0f, 0.0f, - -1.0f, 3.0f, 0.0f, 2.0f - }; - // clang-format on - (void)ScreenFillingTriangle; // Currently unused -} - -void Scene3D::Shutdown() { - if (!IsInit) return; - if (Renderables) delete[] Renderables; -} - -void Scene3D::Update(float dt) { - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - if (Renderables[i]->Status == LoadStatus::Loaded) { - Renderables[i]->Update(dt); - } - } -} -void Scene3D::Render() { - RectF viewport = Window->GetViewport(); - MainCamera.AspectRatio = viewport.Width / viewport.Height; - MainCamera.Recalculate(); - - Renderable3D::BeginFrame(this, &MainCamera); - - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - if (Renderables[i]->Status == LoadStatus::Loaded && - Renderables[i]->StaticModel->Type == ModelType_Background) { - Renderables[i]->Render(); - } - } - - for (int i = 0; i < Profile::Scene3D::MaxRenderables; i++) { - if (Renderables[i]->Status == LoadStatus::Loaded && - Renderables[i]->StaticModel->Type == ModelType_Character) { - Renderables[i]->Render(); - } - } -} - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/3d/scene.h b/src/renderer/vulkan/3d/scene.h deleted file mode 100644 index d92189468..000000000 --- a/src/renderer/vulkan/3d/scene.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -#include "../../3d/scene.h" -#include "../window.h" -#include "../renderer.h" - -namespace Impacto { -namespace Vulkan { - -class Scene3D : public IScene3D { - public: - Scene3D(VulkanWindow* window, VkDevice device, VkRenderPass renderPass, - VkCommandBuffer* commandBuffers); - - void Init(); - void Shutdown(); - void Update(float dt); - void Render(); - - private: - bool IsInit = false; - - VulkanWindow* Window; - VkDevice Device; - VkRenderPass RenderPass; - VkCommandBuffer* CommandBuffers; -}; - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/nv12frame.cpp b/src/renderer/vulkan/nv12frame.cpp deleted file mode 100644 index ca18ad347..000000000 --- a/src/renderer/vulkan/nv12frame.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include "nv12frame.h" - -namespace Impacto { -namespace Vulkan { - -void VkNV12Frame::Init(float width, float height) { - Width = width; - Height = height; - - VkDeviceSize imageSize = (VkDeviceSize)(width * height); - VkDeviceSize bufferSize = - imageSize + 2 * (((VkDeviceSize)width / 2) * ((VkDeviceSize)height / 2)); - - StagingBuffer = CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - vmaMapMemory(Allocator, StagingBuffer.Allocation, &MappedStagingBuffer); - - VkExtent3D lumaImageExtent; - lumaImageExtent.width = static_cast(width); - lumaImageExtent.height = static_cast(height); - lumaImageExtent.depth = 1; - - VkExtent3D cbCrImageExtent; - cbCrImageExtent.width = static_cast(width / 2); - cbCrImageExtent.height = static_cast(height / 2); - cbCrImageExtent.depth = 1; - - auto lumaImageInfo = - GetImageCreateInfo(VK_FORMAT_R8_UNORM, lumaImageExtent, - VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT); - VmaAllocationCreateInfo dimgAllocinfo = {}; - dimgAllocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - vmaCreateImage(Allocator, &lumaImageInfo, &dimgAllocinfo, - &LumaImage.Image.Image, &LumaImage.Image.Allocation, nullptr); - auto cbcrImageInfo = - GetImageCreateInfo(VK_FORMAT_R8G8_UNORM, cbCrImageExtent, - VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT); - vmaCreateImage(Allocator, &cbcrImageInfo, &dimgAllocinfo, - &CbCrImage.Image.Image, &CbCrImage.Image.Allocation, nullptr); - - VkImageViewCreateInfo imageInfo = {}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageInfo.pNext = nullptr; - imageInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageInfo.image = LumaImage.Image.Image; - imageInfo.format = VK_FORMAT_R8_UNORM; - imageInfo.subresourceRange.baseMipLevel = 0; - imageInfo.subresourceRange.levelCount = 1; - imageInfo.subresourceRange.baseArrayLayer = 0; - imageInfo.subresourceRange.layerCount = 1; - imageInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - vkCreateImageView(MainUploadContext.Device, &imageInfo, nullptr, - &LumaImage.ImageView); - - imageInfo.image = CbCrImage.Image.Image; - imageInfo.format = VK_FORMAT_R8G8_UNORM; - vkCreateImageView(MainUploadContext.Device, &imageInfo, nullptr, - &CbCrImage.ImageView); -} - -void Impacto::Vulkan::VkNV12Frame::Submit(const void* luma, int lumaStride, - const void* cbcr, int cbcrStride) { - const int cbcrOffset = (int)(Width * Height); - - const uint8_t* src = (const uint8_t*)luma; - uint8_t* dst = (uint8_t*)MappedStagingBuffer; - for (int y = 0; y < Height; y++) { - memcpy(dst, src, (int)Width); - src += lumaStride; - dst += (int)Width; - } - - src = (const uint8_t*)cbcr; - dst = (uint8_t*)MappedStagingBuffer + cbcrOffset; - for (int y = 0; y < (int)Height / 2; y++) { - memcpy(dst, src, (int)Width); - src += cbcrStride; - dst += (int)Width; - } - - ImmediateSubmit([&](VkCommandBuffer cmd) { - VkExtent3D lumaImageExtent; - lumaImageExtent.width = static_cast(Width); - lumaImageExtent.height = static_cast(Height); - lumaImageExtent.depth = 1; - VkExtent3D cbCrImageExtent; - cbCrImageExtent.width = static_cast(Width / 2); - cbCrImageExtent.height = static_cast(Height / 2); - cbCrImageExtent.depth = 1; - - VkImageSubresourceRange range; - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - range.baseMipLevel = 0; - range.levelCount = 1; - range.baseArrayLayer = 0; - range.layerCount = 1; - - VkImageMemoryBarrier imageBarrierToTransfer = {}; - imageBarrierToTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToTransfer.image = LumaImage.Image.Image; - imageBarrierToTransfer.subresourceRange = range; - imageBarrierToTransfer.srcAccessMask = 0; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = 0; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = 0; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = 1; - copyRegion.imageExtent = lumaImageExtent; - vkCmdCopyBufferToImage(cmd, StagingBuffer.Buffer, LumaImage.Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); - - VkImageMemoryBarrier imageBarrierToReadable = imageBarrierToTransfer; - imageBarrierToReadable.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToReadable.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imageBarrierToReadable.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageBarrierToReadable.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &imageBarrierToReadable); - - imageBarrierToTransfer.image = CbCrImage.Image.Image; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - copyRegion.bufferOffset = (VkDeviceSize)(Width * Height); - copyRegion.imageExtent = cbCrImageExtent; - vkCmdCopyBufferToImage(cmd, StagingBuffer.Buffer, CbCrImage.Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); - - imageBarrierToReadable.image = CbCrImage.Image.Image; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &imageBarrierToReadable); - }); -} - -void VkNV12Frame::Release() { - vmaUnmapMemory(Allocator, StagingBuffer.Allocation); -} - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/nv12frame.h b/src/renderer/vulkan/nv12frame.h deleted file mode 100644 index bc725f637..000000000 --- a/src/renderer/vulkan/nv12frame.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "../nv12frame.h" -#include "utils.h" - -#include - -namespace Impacto { -namespace Vulkan { - -class VkNV12Frame : public NV12Frame { - friend class Renderer; - - public: - void Init(float width, float height) override; - - void Submit(const void* luma, int lumaStride, const void* cbcr, - int cbcrStride) override; - void Release() override; - - protected: - VkTexture LumaImage{}; - VkTexture CbCrImage{}; - - private: - AllocatedBuffer StagingBuffer; - void* MappedStagingBuffer; -}; - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/pipeline.cpp b/src/renderer/vulkan/pipeline.cpp deleted file mode 100644 index 696dcc68c..000000000 --- a/src/renderer/vulkan/pipeline.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "pipeline.h" - -#include - -#include "../../log.h" -#include "../../util.h" -#include "renderer.h" - -namespace Impacto { -namespace Vulkan { - -static char const ShaderPath[] = "./shaders/vulkan"; -static char const FragShaderExtension[] = "_frag.spv"; -static char const VertShaderExtension[] = "_vert.spv"; - -Pipeline::Pipeline(VkDevice device, VkRenderPass renderPass) { - Device = device; - RenderPass = renderPass; - - VkPipelineRasterizationStateCreateInfo rasterizer{}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_NONE; - rasterizer.depthBiasEnable = VK_FALSE; - RasterizerInfo = rasterizer; - - VkPipelineDepthStencilStateCreateInfo depthStencil{}; - depthStencil.sType = - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencil.depthTestEnable = VK_FALSE; - depthStencil.depthWriteEnable = VK_FALSE; - depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; - depthStencil.depthBoundsTestEnable = VK_FALSE; - depthStencil.stencilTestEnable = VK_FALSE; - DepthStencilInfo = depthStencil; -} - -void Pipeline::SetRasterizerInfo( - VkPipelineRasterizationStateCreateInfo rasterizerInfo) { - RasterizerInfo = rasterizerInfo; -} - -void Pipeline::SetDepthStencilInfo( - VkPipelineDepthStencilStateCreateInfo depthStencilInfo) { - DepthStencilInfo = depthStencilInfo; -} - -void Pipeline::SetPushConstants(VkPushConstantRange* pushConstantRange, - int count) { - PushConstantRange = pushConstantRange; - PushConstantRangeCount = count; -} - -void Pipeline::CreateWithShader( - char const* name, VkVertexInputBindingDescription bindingDescription, - VkVertexInputAttributeDescription* attributeDescriptions, - size_t attributeNum, VkDescriptorSetLayout setLayout, bool enableBlending) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Creating pipeline with shader \"{:s}\"\n", name); - - size_t vertShaderCodeSize; - std::string vertexShaderPath = fmt::format(FMT_COMPILE("{}/{}{}"), ShaderPath, - name, VertShaderExtension); - char* vertShaderCode = - (char*)SDL_LoadFile(vertexShaderPath.c_str(), &vertShaderCodeSize); - if (!vertShaderCode) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to read shader source file\n"); - Window->Shutdown(); - } - - size_t fragShaderCodeSize; - std::string fragShaderPath = fmt::format(FMT_COMPILE("{}/{}{}"), ShaderPath, - name, FragShaderExtension); - char* fragShaderCode = - (char*)SDL_LoadFile(fragShaderPath.c_str(), &fragShaderCodeSize); - if (!fragShaderCode) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to read shader source file\n"); - Window->Shutdown(); - } - - VkShaderModule vertShaderModule = - CreateShaderModule(vertShaderCode, vertShaderCodeSize); - VkShaderModule fragShaderModule = - CreateShaderModule(fragShaderCode, fragShaderCodeSize); - - VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; - vertShaderStageInfo.sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = vertShaderModule; - vertShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; - fragShaderStageInfo.sType = - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = fragShaderModule; - fragShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, - fragShaderStageInfo}; - - VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; - vertexInputInfo.sType = - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 1; - vertexInputInfo.vertexAttributeDescriptionCount = - static_cast(attributeNum); - vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; - vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; - inputAssembly.sType = - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - VkPipelineViewportStateCreateInfo viewportState{}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.scissorCount = 1; - - VkPipelineMultisampleStateCreateInfo multisampling{}; - multisampling.sType = - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = (VkSampleCountFlagBits)Window->MsaaCount; - - VkPipelineColorBlendAttachmentState colorBlendAttachment{}; - if (enableBlending) { - colorBlendAttachment.colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_TRUE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstColorBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; - colorBlendAttachment.dstAlphaBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - } else { - colorBlendAttachment.colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - } - - VkPipelineColorBlendStateCreateInfo colorBlending{}; - colorBlending.sType = - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_FALSE; - colorBlending.logicOp = VK_LOGIC_OP_COPY; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - colorBlending.blendConstants[0] = 0.0f; - colorBlending.blendConstants[1] = 0.0f; - colorBlending.blendConstants[2] = 0.0f; - colorBlending.blendConstants[3] = 0.0f; - - std::vector dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR}; - VkPipelineDynamicStateCreateInfo dynamicState{}; - dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicState.dynamicStateCount = static_cast(dynamicStates.size()); - dynamicState.pDynamicStates = dynamicStates.data(); - - VkDescriptorSetLayout texturedSetLayouts[] = {setLayout}; - - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 1; - pipelineLayoutInfo.pSetLayouts = texturedSetLayouts; - pipelineLayoutInfo.pPushConstantRanges = PushConstantRange; - pipelineLayoutInfo.pushConstantRangeCount = PushConstantRangeCount; - - if (vkCreatePipelineLayout(Device, &pipelineLayoutInfo, nullptr, - &PipelineLayout) != VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create pipeline layout!"); - Window->Shutdown(); - } - - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.stageCount = 2; - pipelineInfo.pStages = shaderStages; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &RasterizerInfo; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.pDynamicState = &dynamicState; - pipelineInfo.pDepthStencilState = &DepthStencilInfo; - pipelineInfo.layout = PipelineLayout; - pipelineInfo.renderPass = RenderPass; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - - if (vkCreateGraphicsPipelines(Device, VK_NULL_HANDLE, 1, &pipelineInfo, - nullptr, &GraphicsPipeline) != VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create graphics pipeline!"); - Window->Shutdown(); - } - - vkDestroyShaderModule(Device, fragShaderModule, nullptr); - vkDestroyShaderModule(Device, vertShaderModule, nullptr); -} - -VkShaderModule Pipeline::CreateShaderModule(char const* code, size_t codeSize) { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = codeSize; - createInfo.pCode = reinterpret_cast(code); - - VkShaderModule shaderModule; - if (vkCreateShaderModule(Device, &createInfo, nullptr, &shaderModule) != - VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create shader module!"); - Window->Shutdown(); - } - - return shaderModule; -} - -Pipeline::~Pipeline() { - vkDestroyPipeline(Device, GraphicsPipeline, nullptr); - vkDestroyPipelineLayout(Device, PipelineLayout, nullptr); -} - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/pipeline.h b/src/renderer/vulkan/pipeline.h deleted file mode 100644 index 6988337b3..000000000 --- a/src/renderer/vulkan/pipeline.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -namespace Impacto { -namespace Vulkan { - -class Pipeline { - public: - Pipeline(VkDevice device, VkRenderPass renderPass); - ~Pipeline(); - void SetRasterizerInfo(VkPipelineRasterizationStateCreateInfo rasterizerInfo); - void SetDepthStencilInfo( - VkPipelineDepthStencilStateCreateInfo depthStencilInfo); - void SetPushConstants(VkPushConstantRange* pushConstantRange, int count); - void CreateWithShader( - char const* name, VkVertexInputBindingDescription bindingDescription, - VkVertexInputAttributeDescription* attributeDescriptions, - size_t attributeNum, VkDescriptorSetLayout setLayout, - bool enableBlending = true); - - VkPipeline GraphicsPipeline; - VkPipelineLayout PipelineLayout; - - private: - void CreateRenderPass(VkFormat swapChainImageFormat); - VkShaderModule CreateShaderModule(char const* code, size_t codeSize); - - VkDevice Device; - VkRenderPass RenderPass; - VkPipelineRasterizationStateCreateInfo RasterizerInfo; - VkPipelineDepthStencilStateCreateInfo DepthStencilInfo; - VkPushConstantRange* PushConstantRange = 0; - int PushConstantRangeCount = 0; -}; - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/renderer.cpp b/src/renderer/vulkan/renderer.cpp deleted file mode 100644 index 1301ec772..000000000 --- a/src/renderer/vulkan/renderer.cpp +++ /dev/null @@ -1,2033 +0,0 @@ -#include "renderer.h" - -#include -#include - -#include "../../profile/game.h" -#include "../../game.h" -#include "../../log.h" -#include "3d/scene.h" -#include "yuvframe.h" -#include "nv12frame.h" - -#ifndef IMPACTO_DISABLE_IMGUI -#include -#endif - -namespace Impacto { -namespace Vulkan { - -VkVertexInputBindingDescription Renderer::GetBindingDescription() { - VkVertexInputBindingDescription bindingDescription{}; - bindingDescription.binding = 0; - bindingDescription.stride = sizeof(VertexBufferSprites); - bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - return bindingDescription; -} - -std::array -Renderer::GetAttributeDescriptions() { - std::array attributeDescriptions{}; - - attributeDescriptions[0].binding = 0; - attributeDescriptions[0].location = 0; - attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT; - attributeDescriptions[0].offset = offsetof(VertexBufferSprites, Position); - - attributeDescriptions[1].binding = 0; - attributeDescriptions[1].location = 1; - attributeDescriptions[1].format = VK_FORMAT_R32G32_SFLOAT; - attributeDescriptions[1].offset = offsetof(VertexBufferSprites, UV); - - attributeDescriptions[2].binding = 0; - attributeDescriptions[2].location = 2; - attributeDescriptions[2].format = VK_FORMAT_R32G32B32A32_SFLOAT; - attributeDescriptions[2].offset = offsetof(VertexBufferSprites, Tint); - - attributeDescriptions[3].binding = 0; - attributeDescriptions[3].location = 3; - attributeDescriptions[3].format = VK_FORMAT_R32G32_SFLOAT; - attributeDescriptions[3].offset = offsetof(VertexBufferSprites, MaskUV); - - return attributeDescriptions; -} - -static VKAPI_ATTR VkBool32 VKAPI_CALL -DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, - void* pUserData) { - Impacto::ImpLog(LogLevel::Debug, LogChannel::Render, - "validation layer: {:s}\n", pCallbackData->pMessage); - return VK_FALSE; -} - -VkResult CreateDebugUtilsMessengerEXT( - VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDebugUtilsMessengerEXT* pDebugMessenger) { - auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - instance, "vkCreateDebugUtilsMessengerEXT"); - if (func != nullptr) { - return func(instance, pCreateInfo, pAllocator, pDebugMessenger); - } else { - return VK_ERROR_EXTENSION_NOT_PRESENT; - } -} - -void DestroyDebugUtilsMessengerEXT(VkInstance instance, - VkDebugUtilsMessengerEXT debugMessenger, - const VkAllocationCallbacks* pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != nullptr) { - func(instance, debugMessenger, pAllocator); - } -} - -void Renderer::CreateInstance() { - Uint32 extensionCount = 0; - char const* const* sdlExtensionNames = - SDL_Vulkan_GetInstanceExtensions(&extensionCount); - std::vector extensionNames(sdlExtensionNames, - sdlExtensionNames + extensionCount); - - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = Profile::Game::WindowName.c_str(); - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "impacto"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_1; - - VkInstanceCreateInfo instanceCreateInfo = {}; - instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instanceCreateInfo.pApplicationInfo = &appInfo; -#ifdef __APPLE__ - extensionNames.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - instanceCreateInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; -#endif - if (EnableValidationLayers) { - extensionNames.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } - instanceCreateInfo.enabledExtensionCount = (uint32_t)extensionNames.size(); - instanceCreateInfo.ppEnabledExtensionNames = extensionNames.data(); - - VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &Instance); - - if (result != VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create Vulkan instance! 0x{:04x}\n", - to_underlying(result)); - Window->Shutdown(); - } -} - -void Renderer::SetupDebug() { - if (!EnableValidationLayers) return; - - VkDebugUtilsMessengerCreateInfoEXT createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - createInfo.pfnUserCallback = DebugCallback; - createInfo.pUserData = nullptr; - if (CreateDebugUtilsMessengerEXT(Instance, &createInfo, nullptr, - &DebugMessenger) != VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create Vulkan debug!"); - Window->Shutdown(); - } -} - -void Renderer::PickPhysicalDevice() { - uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(Instance, &deviceCount, nullptr); - - if (deviceCount == 0) { - ImpLog(LogLevel::Error, LogChannel::Render, - "No suitable video adapter found!"); - Window->Shutdown(); - } - - std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(Instance, &deviceCount, devices.data()); - - // TODO: Implement proper device selection - PhysicalDevice = devices[0]; -} - -void Renderer::FindQueues() { - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueFamilyCount, - nullptr); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice, &queueFamilyCount, - queueFamilies.data()); - - QueueIndices.GraphicsQueueIdx = 0xFFFFFFFF; - QueueIndices.PresentQueueIdx = 0xFFFFFFFF; - int i = 0; - for (const auto& queueFamily : queueFamilies) { - if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - QueueIndices.GraphicsQueueIdx = i; - } - - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(PhysicalDevice, i, Surface, - &presentSupport); - if (presentSupport) QueueIndices.PresentQueueIdx = i; - - if (QueueIndices.GraphicsQueueIdx != 0xFFFFFFFF && - QueueIndices.PresentQueueIdx != 0xFFFFFFFF) - return; - - i++; - } -} - -void Renderer::CreateLogicalDevice() { - FindQueues(); - - if (QueueIndices.GraphicsQueueIdx == 0xFFFFFFFF) { - ImpLog(LogLevel::Error, LogChannel::Render, "No graphics queue found!"); - Window->Shutdown(); - } - - const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME}; - - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {QueueIndices.GraphicsQueueIdx, - QueueIndices.PresentQueueIdx}; - - float queuePriority = 1.0f; - for (uint32_t queueFamily : uniqueQueueFamilies) { - VkDeviceQueueCreateInfo queueCreateInfo{}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = queueFamily; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &queuePriority; - queueCreateInfos.push_back(queueCreateInfo); - } - - VkPhysicalDeviceFeatures deviceFeatures{}; - deviceFeatures.samplerAnisotropy = VK_TRUE; - - VkDeviceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - createInfo.queueCreateInfoCount = - static_cast(queueCreateInfos.size()); - createInfo.pQueueCreateInfos = queueCreateInfos.data(); - createInfo.pEnabledFeatures = &deviceFeatures; - createInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size(); - createInfo.ppEnabledExtensionNames = deviceExtensions.data(); - - if (vkCreateDevice(PhysicalDevice, &createInfo, nullptr, &Device) != - VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create logical device!"); - Window->Shutdown(); - } - - vkGetDeviceQueue(Device, QueueIndices.GraphicsQueueIdx, 0, &GraphicsQueue); - vkGetDeviceQueue(Device, QueueIndices.PresentQueueIdx, 0, &PresentQueue); - - CreateAllocator(PhysicalDevice, Device, Instance); - - vkCmdPushDescriptorSetKHR = - (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr( - Device, "vkCmdPushDescriptorSetKHR"); - - MainUploadContext.Device = Device; - MainUploadContext.GraphicsQueue = GraphicsQueue; -} - -void Renderer::CreateSurface() { - if (!SDL_Vulkan_CreateSurface(Window->SDLWindow, Instance, nullptr, - &Surface)) { - ImpLog(LogLevel::Error, LogChannel::Render, "Failed to create surface!"); - Window->Shutdown(); - } -} - -void Renderer::CreateSwapChain() { - VkSurfaceCapabilitiesKHR surfaceCapabilities; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysicalDevice, Surface, - &surfaceCapabilities); - - uint32_t surfaceFormatsCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(PhysicalDevice, Surface, - &surfaceFormatsCount, nullptr); - std::vector surfaceFormats(surfaceFormatsCount); - vkGetPhysicalDeviceSurfaceFormatsKHR( - PhysicalDevice, Surface, &surfaceFormatsCount, surfaceFormats.data()); - - int width, height = 0; - SDL_GetWindowSizeInPixels(Window->SDLWindow, &width, &height); - - SwapChainExtent.width = width; - SwapChainExtent.height = height; - SwapChainImageFormat = surfaceFormats[0].format; - - uint32_t imageCount = surfaceCapabilities.minImageCount + 1; - if (surfaceCapabilities.maxImageCount > 0 && - imageCount > surfaceCapabilities.maxImageCount) { - imageCount = surfaceCapabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = Surface; - createInfo.minImageCount = surfaceCapabilities.minImageCount; - createInfo.imageFormat = SwapChainImageFormat; - createInfo.imageColorSpace = surfaceFormats[0].colorSpace; - createInfo.imageExtent = SwapChainExtent; - createInfo.imageArrayLayers = 1; - createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - uint32_t queueFamilyIndices[] = {QueueIndices.GraphicsQueueIdx, - QueueIndices.PresentQueueIdx}; - if (QueueIndices.GraphicsQueueIdx != QueueIndices.PresentQueueIdx) { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices; - } else { - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - } - - createInfo.preTransform = surfaceCapabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; // Vsync, kind of - createInfo.clipped = VK_TRUE; - - vkCreateSwapchainKHR(Device, &createInfo, nullptr, &SwapChain); - - uint32_t swapChainImageCount = 0; - vkGetSwapchainImagesKHR(Device, SwapChain, &swapChainImageCount, nullptr); - SwapChainImages.resize(swapChainImageCount); - vkGetSwapchainImagesKHR(Device, SwapChain, &swapChainImageCount, - SwapChainImages.data()); -} - -void Renderer::CreateImageViews() { - SwapChainImageViews.resize(SwapChainImages.size()); - for (size_t i = 0; i < SwapChainImages.size(); i++) { - VkImageViewCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - createInfo.image = SwapChainImages[i]; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - createInfo.format = SwapChainImageFormat; - createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - createInfo.subresourceRange.baseMipLevel = 0; - createInfo.subresourceRange.levelCount = 1; - createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(Device, &createInfo, nullptr, - &SwapChainImageViews[i]) != VK_SUCCESS) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create image view!"); - Window->Shutdown(); - } - } -} - -void Renderer::CreateRenderPass() { - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = SwapChainImageFormat; - colorAttachment.samples = (VkSampleCountFlagBits)Window->MsaaCount; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference colorAttachmentRef{}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentDescription depthAttachment{}; - depthAttachment.format = VK_FORMAT_D32_SFLOAT; - depthAttachment.samples = (VkSampleCountFlagBits)Window->MsaaCount; - depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - depthAttachment.finalLayout = - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthAttachmentRef{}; - depthAttachmentRef.attachment = 1; - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentDescription colorAttachmentResolve{}; - colorAttachmentResolve.format = SwapChainImageFormat; - colorAttachmentResolve.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachmentResolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachmentResolve.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachmentResolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachmentResolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachmentResolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachmentResolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentResolveRef{}; - colorAttachmentResolveRef.attachment = 2; - colorAttachmentResolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass{}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - subpass.pDepthStencilAttachment = &depthAttachmentRef; - if (Window->MsaaCount > 1) - subpass.pResolveAttachments = &colorAttachmentResolveRef; - - VkSubpassDependency dependency{}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - - VkAttachmentDescription attachments[3] = {colorAttachment, depthAttachment, - colorAttachmentResolve}; - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = Window->MsaaCount > 1 ? 3 : 2; - renderPassInfo.pAttachments = attachments; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(Device, &renderPassInfo, nullptr, &RenderPass) != - VK_SUCCESS) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to read create render pass!\n"); - Window->Shutdown(); - } -} - -void Renderer::CreateFramebuffers() { - SwapChainFramebuffers.resize(SwapChainImageViews.size()); - for (size_t i = 0; i < SwapChainImageViews.size(); i++) { - VkImageView attachments[] = {ColorImageView, DepthImageView, - SwapChainImageViews[i]}; - if (Window->MsaaCount == 1) attachments[0] = attachments[2]; - - VkFramebufferCreateInfo framebufferInfo{}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = RenderPass; - framebufferInfo.attachmentCount = Window->MsaaCount > 1 ? 3 : 2; - framebufferInfo.pAttachments = attachments; - framebufferInfo.width = SwapChainExtent.width; - framebufferInfo.height = SwapChainExtent.height; - framebufferInfo.layers = 1; - - if (vkCreateFramebuffer(Device, &framebufferInfo, nullptr, - &SwapChainFramebuffers[i]) != VK_SUCCESS) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to create framebuffer!\n"); - Window->Shutdown(); - } - } -} - -void Renderer::CreateCommandPool() { - VkCommandPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - poolInfo.queueFamilyIndex = QueueIndices.GraphicsQueueIdx; - if ((vkCreateCommandPool(Device, &poolInfo, nullptr, &CommandPool) != - VK_SUCCESS) || - (vkCreateCommandPool(Device, &poolInfo, nullptr, - &MainUploadContext.CommandPool) != VK_SUCCESS)) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to create command pool!\n"); - Window->Shutdown(); - } -} - -void Renderer::CreateCommandBuffer() { - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = CommandPool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT; - - if ((vkAllocateCommandBuffers(Device, &allocInfo, CommandBuffers) != - VK_SUCCESS) || - (vkAllocateCommandBuffers(Device, &allocInfo, - &MainUploadContext.CommandBuffer) != - VK_SUCCESS)) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to allocate command buffers!\n"); - Window->Shutdown(); - } -} - -void Renderer::CreateSyncObjects() { - VkSemaphoreCreateInfo semaphoreInfo{}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fenceInfo{}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(Device, &semaphoreInfo, nullptr, - &ImageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(Device, &semaphoreInfo, nullptr, - &RenderFinishedSemaphores[i]) != VK_SUCCESS || - vkCreateFence(Device, &fenceInfo, nullptr, &InFlightFences[i]) != - VK_SUCCESS || - vkCreateFence(Device, &fenceInfo, nullptr, - &MainUploadContext.UploadFence) != VK_SUCCESS) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to create synchronization objects for a frame!\n"); - Window->Shutdown(); - } - } -} - -void Renderer::CreateVertexBuffer() { - VertexBufferAlloc = - CreateBuffer(VertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - - void* data; - vmaMapMemory(Allocator, VertexBufferAlloc.Allocation, &data); - VertexBuffer = (uint8_t*)data; -} - -void Renderer::CreateIndexBuffer() { - IndexBufferAlloc = - CreateBuffer(IndexBufferCount, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - - void* data; - vmaMapMemory(Allocator, IndexBufferAlloc.Allocation, &data); - IndexBuffer = (uint16_t*)data; -} - -void Renderer::CreateDescriptors() { - std::vector sizes = { - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 10}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 10}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 10}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 100}}; - - VkDescriptorPoolCreateInfo poolInfo = {}; - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - poolInfo.maxSets = 100; - poolInfo.poolSizeCount = (uint32_t)sizes.size(); - poolInfo.pPoolSizes = sizes.data(); - vkCreateDescriptorPool(Device, &poolInfo, nullptr, &DescriptorPool); - - VkDescriptorSetLayoutBinding textureBind = {}; - textureBind.binding = 0; - textureBind.descriptorCount = 1; - textureBind.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - textureBind.pImmutableSamplers = nullptr; - textureBind.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutCreateInfo textureBindInfo = {}; - textureBindInfo.bindingCount = 1; - textureBindInfo.flags = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - textureBindInfo.pNext = nullptr; - textureBindInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - textureBindInfo.pBindings = &textureBind; - - vkCreateDescriptorSetLayout(Device, &textureBindInfo, nullptr, - &SingleTextureSetLayout); - - VkDescriptorSetLayoutBinding textureBinds; - textureBinds.binding = 0; - textureBinds.descriptorCount = 2; - textureBinds.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - textureBinds.pImmutableSamplers = nullptr; - textureBinds.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - - VkDescriptorSetLayoutCreateInfo texturesBindInfo = {}; - texturesBindInfo.bindingCount = 1; - texturesBindInfo.flags = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - texturesBindInfo.pNext = nullptr; - texturesBindInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - texturesBindInfo.pBindings = &textureBinds; - - vkCreateDescriptorSetLayout(Device, &texturesBindInfo, nullptr, - &DoubleTextureSetLayout); - - textureBinds.descriptorCount = 3; - vkCreateDescriptorSetLayout(Device, &texturesBindInfo, nullptr, - &TripleTextureSetLayout); -} - -void Renderer::CreateColorAndDepthImage() { - VkExtent3D imageExtent; - imageExtent.width = SwapChainExtent.width; - imageExtent.height = SwapChainExtent.height; - imageExtent.depth = 1; - - // Color image - VkImageCreateInfo cimgInfo = - GetImageCreateInfo(SwapChainImageFormat, imageExtent, - static_cast(Window->MsaaCount)); - cimgInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - cimgInfo.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - VmaAllocationCreateInfo cimgAllocinfo = {}; - cimgAllocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - vmaCreateImage(Allocator, &cimgInfo, &cimgAllocinfo, &ColorImage.Image, - &ColorImage.Allocation, nullptr); - - VkImageViewCreateInfo colorImageInfo = {}; - colorImageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - colorImageInfo.pNext = nullptr; - colorImageInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageInfo.image = ColorImage.Image; - colorImageInfo.format = SwapChainImageFormat; - colorImageInfo.subresourceRange.baseMipLevel = 0; - colorImageInfo.subresourceRange.levelCount = 1; - colorImageInfo.subresourceRange.baseArrayLayer = 0; - colorImageInfo.subresourceRange.layerCount = 1; - colorImageInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCreateImageView(Device, &colorImageInfo, nullptr, &ColorImageView); - - // Depth image - VkImageCreateInfo dimgInfo = - GetImageCreateInfo(VK_FORMAT_D32_SFLOAT, imageExtent, - static_cast(Window->MsaaCount)); - dimgInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - dimgInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - VmaAllocationCreateInfo dimgAllocinfo = {}; - dimgAllocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - vmaCreateImage(Allocator, &dimgInfo, &dimgAllocinfo, &DepthImage.Image, - &DepthImage.Allocation, nullptr); - - VkImageViewCreateInfo imageInfo = {}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageInfo.pNext = nullptr; - imageInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageInfo.image = DepthImage.Image; - imageInfo.format = VK_FORMAT_D32_SFLOAT; - imageInfo.subresourceRange.baseMipLevel = 0; - imageInfo.subresourceRange.levelCount = 1; - imageInfo.subresourceRange.baseArrayLayer = 0; - imageInfo.subresourceRange.layerCount = 1; - imageInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - vkCreateImageView(Device, &imageInfo, nullptr, &DepthImageView); -} - -void Renderer::CleanupSwapChain() { - for (size_t i = 0; i < SwapChainFramebuffers.size(); i++) { - vkDestroyFramebuffer(Device, SwapChainFramebuffers[i], nullptr); - } - - for (size_t i = 0; i < SwapChainImageViews.size(); i++) { - vkDestroyImageView(Device, SwapChainImageViews[i], nullptr); - } - - vkDestroySwapchainKHR(Device, SwapChain, nullptr); -} - -void Renderer::RecreateSwapChain() { - vkDeviceWaitIdle(Device); - - CleanupSwapChain(); - - CreateSwapChain(); - CreateImageViews(); - CreateFramebuffers(); -} - -void Renderer::Init() { - if (IsInit) return; - ImpLog(LogLevel::Info, LogChannel::Render, - "Initializing Renderer2D Vulkan system\n"); - IsInit = true; - - CurrentFrameIndex = 0; - CurrentImageIndex = 0; - - VkWindow = new VulkanWindow(); - VkWindow->Init(); - Window = (BaseWindow*)VkWindow; - - CreateInstance(); - SetupDebug(); - PickPhysicalDevice(); - CreateSurface(); - CreateLogicalDevice(); - - CreateSwapChain(); - CreateImageViews(); - CreateColorAndDepthImage(); - CreateRenderPass(); - CreateFramebuffers(); - CreateCommandPool(); - CreateVertexBuffer(); - CreateIndexBuffer(); - CreateCommandBuffer(); - CreateSyncObjects(); - CreateDescriptors(); - - auto attributeDescriptions = GetAttributeDescriptions(); - auto bindingDescription = GetBindingDescription(); - - PipelineSprite = new Pipeline(Device, RenderPass); - PipelineSprite->CreateWithShader( - "Sprite", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), SingleTextureSetLayout); - - PipelineSpriteNoBlending = new Pipeline(Device, RenderPass); - PipelineSpriteNoBlending->CreateWithShader( - "Sprite", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), SingleTextureSetLayout, false); - - PipelineSpriteInverted = new Pipeline(Device, RenderPass); - PipelineSpriteInverted->CreateWithShader( - "Sprite_inverted", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), SingleTextureSetLayout); - - VkPushConstantRange maskedSpritePushConstant; - maskedSpritePushConstant.offset = 0; - maskedSpritePushConstant.size = sizeof(SpritePushConstants); - maskedSpritePushConstant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - PipelineMaskedSprite = new Pipeline(Device, RenderPass); - PipelineMaskedSprite->SetPushConstants(&maskedSpritePushConstant, 1); - PipelineMaskedSprite->CreateWithShader( - "MaskedSprite", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), DoubleTextureSetLayout); - - VkPushConstantRange maskedSpriteNoAlphaPushConstant; - maskedSpriteNoAlphaPushConstant.offset = 0; - maskedSpriteNoAlphaPushConstant.size = sizeof(MaskedNoAlphaPushConstants); - maskedSpriteNoAlphaPushConstant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - PipelineMaskedSpriteNoAlpha = new Pipeline(Device, RenderPass); - PipelineMaskedSpriteNoAlpha->SetPushConstants( - &maskedSpriteNoAlphaPushConstant, 1); - PipelineMaskedSpriteNoAlpha->CreateWithShader( - "MaskedSpriteNoAlpha", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), DoubleTextureSetLayout); - - VkPushConstantRange yuvFramePushConstants; - yuvFramePushConstants.offset = 0; - yuvFramePushConstants.size = sizeof(YUVFramePushConstants); - yuvFramePushConstants.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - PipelineYUVFrame = new Pipeline(Device, RenderPass); - PipelineYUVFrame->SetPushConstants(&yuvFramePushConstants, 1); - PipelineYUVFrame->CreateWithShader( - "YUVFrame", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), TripleTextureSetLayout); - PipelineNV12Frame = new Pipeline(Device, RenderPass); - PipelineNV12Frame->SetPushConstants(&yuvFramePushConstants, 1); - PipelineNV12Frame->CreateWithShader( - "NV12Frame", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), TripleTextureSetLayout); - - VkPushConstantRange ccBoxPushConstant; - ccBoxPushConstant.offset = 0; - ccBoxPushConstant.size = sizeof(CCBoxPushConstants); - ccBoxPushConstant.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - PipelineCCMessageBox = new Pipeline(Device, RenderPass); - PipelineCCMessageBox->SetPushConstants(&ccBoxPushConstant, 1); - PipelineCCMessageBox->CreateWithShader( - "CCMessageBoxSprite", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), DoubleTextureSetLayout); - - PipelineCHLCCMenuBackground = new Pipeline(Device, RenderPass); - PipelineCHLCCMenuBackground->SetPushConstants(&ccBoxPushConstant, 1); - PipelineCHLCCMenuBackground->CreateWithShader( - "CHLCCMenuBackground", bindingDescription, attributeDescriptions.data(), - attributeDescriptions.size(), DoubleTextureSetLayout); - - CurrentPipeline = PipelineSprite; - - if (+Profile::Game::GameFeatures & +GameFeature::Scene3D) { - Scene = new Scene3D(VkWindow, Device, RenderPass, CommandBuffers); - Scene->Init(); - } - - // Make 1x1 white pixel for colored rectangles - Texture rectTexture; - rectTexture.Load1x1(0xFF, 0xFF, 0xFF, 0xFF); - SpriteSheet rectSheet(1.0f, 1.0f); - rectSheet.Texture = rectTexture.Submit(); - RectSprite = Sprite(rectSheet, 0.0f, 0.0f, 1.0f, 1.0f); - - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.pNext = nullptr; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; - samplerInfo.anisotropyEnable = VK_TRUE; - samplerInfo.maxAnisotropy = 16; - vkCreateSampler(Device, &samplerInfo, nullptr, &Sampler); - -#ifndef IMPACTO_DISABLE_IMGUI - // Setup Platform/Renderer backends - ImGui_ImplSDL3_InitForVulkan(VkWindow->SDLWindow); - - ImGui_ImplVulkan_InitInfo imguiInfo = {}; - imguiInfo.Instance = Instance; - imguiInfo.PhysicalDevice = PhysicalDevice; - imguiInfo.Device = Device; - imguiInfo.QueueFamily = QueueIndices.PresentQueueIdx; - imguiInfo.Queue = PresentQueue; - imguiInfo.DescriptorPool = DescriptorPool; - imguiInfo.MinImageCount = 2; - imguiInfo.ImageCount = 2; - imguiInfo.PipelineInfoMain.RenderPass = RenderPass; - imguiInfo.PipelineInfoMain.Subpass = 0; - imguiInfo.PipelineInfoMain.MSAASamples = - (VkSampleCountFlagBits)Window->MsaaCount; - ImGui_ImplVulkan_Init(&imguiInfo); -#endif - - MainRendererInstance = this; -} - -void Renderer::Shutdown() { - if (!IsInit) return; - IsInit = false; - - if (+Profile::Game::GameFeatures & +GameFeature::Scene3D) { - Scene->Shutdown(); - } - - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkWaitForFences(Device, 1, &InFlightFences[i], VK_TRUE, UINT64_MAX); - } - - // Textures are invalidated when freeing, so store keys first - std::vector textureIds; - for (const auto& texture : Textures) { - textureIds.push_back(texture.first); - } - for (uint32_t id : textureIds) { - FreeTexture(id); - } - for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(Device, RenderFinishedSemaphores[i], nullptr); - vkDestroySemaphore(Device, ImageAvailableSemaphores[i], nullptr); - vkDestroyFence(Device, InFlightFences[i], nullptr); - } - vkDestroyCommandPool(Device, CommandPool, nullptr); - vkDestroyRenderPass(Device, RenderPass, nullptr); - vmaUnmapMemory(Allocator, VertexBufferAlloc.Allocation); - vmaDestroyBuffer(Allocator, VertexBufferAlloc.Buffer, - VertexBufferAlloc.Allocation); - vmaUnmapMemory(Allocator, IndexBufferAlloc.Allocation); - vmaDestroyBuffer(Allocator, IndexBufferAlloc.Buffer, - IndexBufferAlloc.Allocation); - vkDestroyImageView(Device, DepthImageView, nullptr); - vmaDestroyImage(Allocator, DepthImage.Image, DepthImage.Allocation); - vkDestroyImageView(Device, ColorImageView, nullptr); - vmaDestroyImage(Allocator, ColorImage.Image, ColorImage.Allocation); - CleanupSwapChain(); - vkDestroySurfaceKHR(Instance, Surface, nullptr); - vkDestroyDevice(Device, nullptr); - if (EnableValidationLayers) { - DestroyDebugUtilsMessengerEXT(Instance, DebugMessenger, nullptr); - } - vkDestroyInstance(Instance, nullptr); -} - -#ifndef IMPACTO_DISABLE_IMGUI -void Renderer::ImGuiBeginFrame() { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplSDL3_NewFrame(); - ImGui::NewFrame(); -} -#endif - -void Renderer::BeginFrame() { - if (Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->BeginFrame() called before EndFrame()\n"); - return; - } - - Drawing = true; - - CurrentTexture = 0; - - vkWaitForFences(Device, 1, &InFlightFences[CurrentFrameIndex], VK_TRUE, - UINT64_MAX); - - vkAcquireNextImageKHR(Device, SwapChain, UINT64_MAX, - ImageAvailableSemaphores[CurrentFrameIndex], - VK_NULL_HANDLE, &CurrentImageIndex); - - vkResetFences(Device, 1, &InFlightFences[CurrentFrameIndex]); - - VkCommandBufferBeginInfo beginInfo{}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; - - vkResetCommandBuffer(CommandBuffers[CurrentFrameIndex], 0); - if (vkBeginCommandBuffer(CommandBuffers[CurrentFrameIndex], &beginInfo) != - VK_SUCCESS) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to begin recording command buffer!\n"); - Window->Shutdown(); - } - - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = RenderPass; - renderPassInfo.framebuffer = SwapChainFramebuffers[CurrentImageIndex]; - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = SwapChainExtent; - renderPassInfo.clearValueCount = 0; - - vkCmdBeginRenderPass(CommandBuffers[CurrentFrameIndex], &renderPassInfo, - VK_SUBPASS_CONTENTS_INLINE); - - VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - VkClearAttachment clearAttachments[2] = {}; - clearAttachments[0].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - clearAttachments[0].clearValue = clearColor; - clearAttachments[0].colorAttachment = 0; - VkClearValue clearDepth = {}; - clearDepth.depthStencil = {1.0f, 0}; - clearAttachments[1].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - clearAttachments[1].clearValue = clearDepth; - VkClearRect clearRect = {}; - clearRect.layerCount = 1; - clearRect.rect.offset = {0, 0}; - clearRect.rect.extent = SwapChainExtent; - - vkCmdClearAttachments(CommandBuffers[CurrentFrameIndex], 2, clearAttachments, - 1, &clearRect); - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->GraphicsPipeline); - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(SwapChainExtent.width); - viewport.height = static_cast(SwapChainExtent.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(CommandBuffers[CurrentFrameIndex], 0, 1, &viewport); - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = SwapChainExtent; - vkCmdSetScissor(CommandBuffers[CurrentFrameIndex], 0, 1, &scissor); - PreviousScissorRect = RectF(0.0f, 0.0f, (float)SwapChainExtent.width, - (float)SwapChainExtent.height); - - VertexBufferOffset = 0; - IndexBufferOffset = 0; -} - -void Renderer::BeginFrame2D() {} - -void Renderer::EndFrame() { - if (!Drawing) return; - Flush(); - -#ifndef IMPACTO_DISABLE_IMGUI - ImGui::Render(); - ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), - CommandBuffers[CurrentFrameIndex]); -#endif - - vkCmdEndRenderPass(CommandBuffers[CurrentFrameIndex]); - if (vkEndCommandBuffer(CommandBuffers[CurrentFrameIndex]) != VK_SUCCESS) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to record command buffer!\n"); - Window->Shutdown(); - } - - VkSubmitInfo submitInfo{}; - VkSemaphore waitSemaphores[] = {ImageAvailableSemaphores[CurrentFrameIndex]}; - VkPipelineStageFlags waitStages[] = { - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - VkSemaphore signalSemaphores[] = { - RenderFinishedSemaphores[CurrentFrameIndex]}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &CommandBuffers[CurrentFrameIndex]; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; - VkResult res = vkQueueSubmit(GraphicsQueue, 1, &submitInfo, - InFlightFences[CurrentFrameIndex]); - if (res != VK_SUCCESS) { - ImpLog(LogLevel::Debug, LogChannel::Render, - "Failed to submit draw command buffer! 0x{:04x}\n", - to_underlying(res)); - Window->Shutdown(); - } - - VkPresentInfoKHR presentInfo{}; - VkSwapchainKHR swapChains[] = {SwapChain}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = swapChains; - presentInfo.pImageIndices = &CurrentImageIndex; - vkQueuePresentKHR(PresentQueue, &presentInfo); - - CurrentFrameIndex = (CurrentFrameIndex + 1) % MAX_FRAMES_IN_FLIGHT; - - Drawing = false; -} - -uint32_t Renderer::SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) { - VkDeviceSize imageSize = 0; - VkFormat imageFormat = VK_FORMAT_R8G8B8A8_SRGB; - uint8_t* newBuffer = nullptr; - - switch (format) { - case TexFmt_RGBA: - imageSize = width * height * 4; - imageFormat = VK_FORMAT_R8G8B8A8_UNORM; - break; - case TexFmt_RGB: { - imageSize = width * height * 4; - imageFormat = VK_FORMAT_R8G8B8A8_UNORM; - newBuffer = (uint8_t*)malloc(imageSize); - int num = width * height; - for (int i = 0; i < num; i++) { - newBuffer[4 * i] = buffer[3 * i]; - newBuffer[4 * i + 1] = buffer[3 * i + 1]; - newBuffer[4 * i + 2] = buffer[3 * i + 2]; - newBuffer[4 * i + 3] = 0xFF; - } - } break; - case TexFmt_U8: - imageSize = width * height; - imageFormat = VK_FORMAT_R8_UNORM; - default: { - } - } - - AllocatedBuffer stagingBuffer = CreateBuffer( - imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - void* data; - vmaMapMemory(Allocator, stagingBuffer.Allocation, &data); - if (format == TexFmt_RGB) { - memcpy(data, newBuffer, static_cast(imageSize)); - free(newBuffer); - } else { - memcpy(data, buffer, static_cast(imageSize)); - } - vmaUnmapMemory(Allocator, stagingBuffer.Allocation); - - VkExtent3D imageExtent; - imageExtent.width = static_cast(width); - imageExtent.height = static_cast(height); - imageExtent.depth = 1; - - VkImageCreateInfo dimgInfo = GetImageCreateInfo( - imageFormat, imageExtent, VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT); - AllocatedImage newImage{}; - VmaAllocationCreateInfo dimgAllocinfo = {}; - dimgAllocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - vmaCreateImage(Allocator, &dimgInfo, &dimgAllocinfo, &newImage.Image, - &newImage.Allocation, nullptr); - - ImmediateSubmit([&](VkCommandBuffer cmd) { - VkImageSubresourceRange range; - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - range.baseMipLevel = 0; - range.levelCount = 1; - range.baseArrayLayer = 0; - range.layerCount = 1; - - VkImageMemoryBarrier imageBarrierToTransfer = {}; - imageBarrierToTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToTransfer.image = newImage.Image; - imageBarrierToTransfer.subresourceRange = range; - imageBarrierToTransfer.srcAccessMask = 0; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = 0; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = 0; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = 1; - copyRegion.imageExtent = imageExtent; - vkCmdCopyBufferToImage(cmd, stagingBuffer.Buffer, newImage.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); - - VkImageMemoryBarrier imageBarrierToReadable = imageBarrierToTransfer; - imageBarrierToReadable.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToReadable.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageBarrierToReadable.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageBarrierToReadable.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &imageBarrierToReadable); - }); - - vmaDestroyBuffer(Allocator, stagingBuffer.Buffer, stagingBuffer.Allocation); - - VkTexture outTexture{}; - outTexture.Image = newImage; - VkImageViewCreateInfo imageInfo = {}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageInfo.pNext = nullptr; - imageInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageInfo.image = outTexture.Image.Image; - imageInfo.format = imageFormat; - imageInfo.subresourceRange.baseMipLevel = 0; - imageInfo.subresourceRange.levelCount = 1; - imageInfo.subresourceRange.baseArrayLayer = 0; - imageInfo.subresourceRange.layerCount = 1; - imageInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - vkCreateImageView(Device, &imageInfo, nullptr, &outTexture.ImageView); - - auto id = NextTextureId; - NextTextureId += 1; - Textures[id] = outTexture; - - return id; -} - -void Renderer::FreeTexture(uint32_t id) { - // TODO: I need to figure this out... images are getting destroyed but are - // still used in draw somehow - // UPDATE: This... seems to just work now? Keep an eye on it I guess - - vmaDestroyImage(Allocator, Textures[id].Image.Image, - Textures[id].Image.Allocation); - vkDestroyImageView(Device, Textures[id].ImageView, nullptr); - Textures.erase(id); -} - -YUVFrame* Renderer::CreateYUVFrame(float width, float height) { - VideoFrameInternalYUV = new VkYUVFrame(); - VideoFrameInternalYUV->Init(width, height); - return (YUVFrame*)VideoFrameInternalYUV; -} - -NV12Frame* Renderer::CreateNV12Frame(float width, float height) { - VideoFrameInternalNV12 = new VkNV12Frame(); - VideoFrameInternalNV12->Init(width, height); - return (NV12Frame*)VideoFrameInternalNV12; -} - -void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, - const glm::mat4 transformation, - const std::span tints, - const glm::vec3 colorShift, const bool inverted, - const bool disableBlend, - const bool textureWrapRepeat) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawSprite() called before BeginFrame()\n"); - return; - } - - if (!sprite.Sheet.Texture) return; - if (Textures.count(sprite.Sheet.Texture) == 0) return; - - // Are we in sprite mode? - if (inverted) - EnsureMode(PipelineSpriteInverted); - else if (disableBlend) - EnsureMode(PipelineSpriteNoBlending); - else - EnsureMode(PipelineSprite); - - // Do we have the texture assigned? - EnsureTextureBound(sprite.Sheet.Texture); - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetPosition(CornersQuad(dest).Transform(transformation), - &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tints[i]; -} - -void Renderer::DrawMaskedSprite( - const Sprite& sprite, const Sprite& mask, const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, const int fadeRange, - const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, - const std::span tints, const bool isInverted, - const bool isSameTexture) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawMaskedSpriteOverlay() called before BeginFrame()\n"); - return; - } - - Flush(); - - if (Textures.count(sprite.Sheet.Texture) == 0 || - Textures.count(mask.Sheet.Texture) == 0) - return; - - alpha = std::clamp(alpha, 0, fadeRange + 256); - const float alphaRange = 256.0f / fadeRange; - const float constAlpha = ((255.0f - alpha) * alphaRange) / 255.0f; - - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.pNext = nullptr; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.anisotropyEnable = VK_TRUE; - samplerInfo.maxAnisotropy = 16; - - VkDescriptorImageInfo imageBufferInfo[2]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = Textures[sprite.Sheet.Texture].ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - vkCreateSampler(Device, &samplerInfo, nullptr, &imageBufferInfo[1].sampler); - imageBufferInfo[1].imageView = Textures[mask.Sheet.Texture].ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 2; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - EnsureMode(PipelineMaskedSprite, true); - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->PipelineLayout, 0, 1, &writeDescriptorSet); - SpritePushConstants constants = {}; - constants.Alpha = glm::vec2(alphaRange, constAlpha); - constants.IsInverted = isInverted; - constants.IsSameTexture = isSameTexture; - vkCmdPushConstants( - CommandBuffers[CurrentFrameIndex], CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(SpritePushConstants), &constants); - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(CornersQuad(maskDest).Transform(maskTransformation), - sprite.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(CornersQuad(spriteDest).Transform(spriteTransformation), - &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tints[i]; -} - -void Renderer::DrawMaskedSpriteOverlay( - const Sprite& sprite, const Sprite& mask, const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, const int fadeRange, - const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, - const std::span tints, const bool isInverted, - const bool useMaskAlpha) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawMaskedSpriteOverlay() called before BeginFrame()\n"); - return; - } - - if (sprite.Sheet.IsScreenCap) Flush(); - - if (Textures.count(sprite.Sheet.Texture) == 0 || - Textures.count(mask.Sheet.Texture) == 0) - return; - - alpha = std::clamp(alpha, 0, fadeRange + 256); - const float alphaRange = 256.0f / fadeRange; - const float constAlpha = ((255.0f - alpha) * alphaRange) / 255.0f; - - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.pNext = nullptr; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.anisotropyEnable = VK_TRUE; - samplerInfo.maxAnisotropy = 16; - - VkDescriptorImageInfo imageBufferInfo[2]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = Textures[sprite.Sheet.Texture].ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - vkCreateSampler(Device, &samplerInfo, nullptr, &imageBufferInfo[1].sampler); - imageBufferInfo[1].imageView = Textures[mask.Sheet.Texture].ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 2; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - if (useMaskAlpha) { - EnsureMode(PipelineMaskedSprite, true); - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->PipelineLayout, 0, 1, &writeDescriptorSet); - SpritePushConstants constants = {}; - constants.Alpha = glm::vec2(alphaRange, constAlpha); - constants.IsInverted = isInverted; - constants.IsSameTexture = false; - vkCmdPushConstants(CommandBuffers[CurrentFrameIndex], - CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, - sizeof(SpritePushConstants), &constants); - - } else { - EnsureMode(PipelineMaskedSpriteNoAlpha, true); - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->PipelineLayout, 0, 1, &writeDescriptorSet); - MaskedNoAlphaPushConstants constants = {}; - constants.Alpha = glm::vec2(alphaRange, constAlpha); - constants.IsInverted = isInverted; - vkCmdPushConstants(CommandBuffers[CurrentFrameIndex], - CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, - sizeof(MaskedNoAlphaPushConstants), &constants); - } - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(CornersQuad(maskDest).Transform(maskTransformation), - mask.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(CornersQuad(spriteDest).Transform(spriteTransformation), - &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tints[i]; -} - -void Renderer::DrawPrimitives( - const SpriteSheet& sheet, const SpriteSheet* const mask, - const ShaderProgramType shaderType, - const std::span vertices, - const std::span indices, - const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, - const bool inverted, TopologyMode topologyMode, bool textureWrapRepeat) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawVertices() called before BeginFrame()\n"); - return; - } - - if (Textures.count(sheet.Texture) == 0) return; - - // The index buffer needs to be flushed - Flush(); - - if (mask != nullptr) { - VkSamplerCreateInfo samplerInfo = {}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.pNext = nullptr; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.anisotropyEnable = VK_TRUE; - samplerInfo.maxAnisotropy = 16; - - VkDescriptorImageInfo imageBufferInfo[2]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = Textures[sheet.Texture].ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - vkCreateSampler(Device, &samplerInfo, nullptr, &imageBufferInfo[1].sampler); - imageBufferInfo[1].imageView = Textures[mask->Texture].ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 2; - writeDescriptorSet.descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - EnsureMode(PipelineMaskedSpriteNoAlpha); - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->PipelineLayout, 0, 1, &writeDescriptorSet); - MaskedNoAlphaPushConstants constants = {}; - constants.Alpha = glm::vec2(1.0f, 0.0f); - constants.IsInverted = inverted; - vkCmdPushConstants(CommandBuffers[CurrentFrameIndex], - CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, - sizeof(MaskedNoAlphaPushConstants), &constants); - } else { - if (inverted) - EnsureMode(PipelineSpriteInverted); - else - EnsureMode(PipelineSprite); - - EnsureTextureBound(sheet.Texture); - } - - // Push vertices - VertexBufferSprites* vertexBuffer = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += vertices.size_bytes(); - - const auto vertexInfoToNDC = [this, spriteTransformation, - maskTransformation](VertexBufferSprites info) { - info.Position = DesignToNDC( - glm::vec2(spriteTransformation * glm::vec4(info.Position, 0.0f, 1.0f))); - info.MaskUV = - glm::vec2(maskTransformation * glm::vec4(info.MaskUV, 0.0f, 1.0f)); - return info; - }; - std::transform(vertices.begin(), vertices.end(), vertexBuffer, - vertexInfoToNDC); - - // Push indices - IndexBufferFill += indices.size(); - size_t indexBufferOffset = IndexBufferOffset / sizeof(uint16_t); - std::ranges::copy(indices, IndexBuffer + indexBufferOffset); - - // Flush again and bind back our buffer - Flush(); -} - -void Renderer::DrawCCMessageBox(Sprite const& sprite, Sprite const& mask, - RectF const& dest, glm::vec4 tint, int alpha, - int fadeRange, float effectCt) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawCCMessageBox() called before BeginFrame()\n"); - return; - } - - if (Textures.count(sprite.Sheet.Texture) == 0 || - Textures.count(mask.Sheet.Texture) == 0) - return; - - if (alpha < 0) alpha = 0; - if (alpha > fadeRange + 256) alpha = fadeRange + 256; - - float alphaRange = 256.0f / fadeRange; - float constAlpha = ((255.0f - alpha) * alphaRange) / 255.0f; - - EnsureMode(PipelineCCMessageBox); - - VkDescriptorImageInfo imageBufferInfo[2]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = Textures[sprite.Sheet.Texture].ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageBufferInfo[1].sampler = Sampler; - imageBufferInfo[1].imageView = Textures[mask.Sheet.Texture].ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 2; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineMaskedSprite->PipelineLayout, 0, 1, &writeDescriptorSet); - - CCBoxPushConstants constants = {}; - constants.CCBoxAlpha = glm::vec4(alphaRange, constAlpha, effectCt, 0.0f); - vkCmdPushConstants( - CommandBuffers[CurrentFrameIndex], CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(CCBoxPushConstants), &constants); - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(mask.Bounds, mask.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tint; -} - -void Renderer::DrawCHLCCMenuBackground(const Sprite& sprite, const Sprite& mask, - const RectF& dest, float alpha) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawCCMessageBox() called before BeginFrame()\n"); - return; - } - - if (Textures.count(sprite.Sheet.Texture) == 0 || - Textures.count(mask.Sheet.Texture) == 0) - return; - - if (alpha < 0.0f) - alpha = 0; - else if (alpha > 1.0f) - alpha = 1.0f; - - EnsureMode(PipelineCHLCCMenuBackground); - - VkDescriptorImageInfo imageBufferInfo[2]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = Textures[sprite.Sheet.Texture].ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageBufferInfo[1].sampler = Sampler; - imageBufferInfo[1].imageView = Textures[mask.Sheet.Texture].ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 2; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineMaskedSprite->PipelineLayout, 0, 1, &writeDescriptorSet); - - CCBoxPushConstants constants = {}; - constants.CCBoxAlpha = glm::vec4(alpha, 0.0f, 0.0f, 0.0f); - vkCmdPushConstants( - CommandBuffers[CurrentFrameIndex], CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(CCBoxPushConstants), &constants); - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(sprite.Bounds, sprite.Sheet.GetDimensions(), &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetUV(mask.Bounds, mask.Sheet.GetDimensions(), &vertices[0].MaskUV, - sizeof(VertexBufferSprites)); - - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); -} - -inline void Renderer::MakeQuad() { - size_t indexBufferOffset = IndexBufferOffset / sizeof(uint16_t); - if (IndexBufferFill + 6 <= IndexBufferCount) { - // bottom-left -> top-left -> top-right - IndexBuffer[indexBufferOffset + IndexBufferFill] = - (uint16_t)VertexBufferCount + 0; - IndexBuffer[indexBufferOffset + IndexBufferFill + 1] = - (uint16_t)VertexBufferCount + 1; - IndexBuffer[indexBufferOffset + IndexBufferFill + 2] = - (uint16_t)VertexBufferCount + 2; - // bottom-left -> top-right -> bottom-right - IndexBuffer[indexBufferOffset + IndexBufferFill + 3] = - (uint16_t)VertexBufferCount + 0; - IndexBuffer[indexBufferOffset + IndexBufferFill + 4] = - (uint16_t)VertexBufferCount + 2; - IndexBuffer[indexBufferOffset + IndexBufferFill + 5] = - (uint16_t)VertexBufferCount + 3; - IndexBufferFill += 6; - VertexBufferCount += 4; - } -} - -void Renderer::EnsureTextureBound(unsigned int texture) { - if (CurrentTexture != texture) { - ImpLogSlow(LogLevel::Trace, LogChannel::Render, - "Renderer->EnsureTextureBound flushing because texture {:d} is " - "not {:d}\n", - CurrentTexture, texture); - Flush(); - - VkDescriptorImageInfo imageBufferInfo; - imageBufferInfo.sampler = Sampler; - imageBufferInfo.imageView = Textures[texture].ImageView; - imageBufferInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 1; - writeDescriptorSet.descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = &imageBufferInfo; - - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - CurrentPipeline->PipelineLayout, 0, 1, &writeDescriptorSet); - - CurrentTexture = texture; - } -} - -void Renderer::EnsureMode(Pipeline* pipeline, bool flush) { - if (CurrentPipeline != pipeline) { - ImpLogSlow(LogLevel::Trace, LogChannel::Render, - "Renderer2D changing mode\n"); - if (flush) Flush(); - vkCmdBindPipeline(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline->GraphicsPipeline); - CurrentPipeline = pipeline; - } -} - -void Renderer::Flush() { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->Flush() called before BeginFrame()\n"); - return; - } - - if (VertexBufferFill > 0 && IndexBufferFill > 0) { - VkBuffer vertexBuffers[] = {VertexBufferAlloc.Buffer}; - VkDeviceSize offsets[] = {(VkDeviceSize)VertexBufferOffset}; - vkCmdBindVertexBuffers(CommandBuffers[CurrentFrameIndex], 0, 1, - vertexBuffers, offsets); - vkCmdBindIndexBuffer(CommandBuffers[CurrentFrameIndex], - IndexBufferAlloc.Buffer, IndexBufferOffset, - VK_INDEX_TYPE_UINT16); - - vkCmdDrawIndexed(CommandBuffers[CurrentFrameIndex], - (uint32_t)IndexBufferFill, 1, 0, 0, 0); - } - IndexBufferOffset += IndexBufferFill * sizeof(uint16_t); - IndexBufferFill = 0; - VertexBufferOffset += VertexBufferFill; - VertexBufferFill = 0; - VertexBufferCount = 0; - CurrentTexture = 0; -} - -void Renderer::DrawVideoTexture(const YUVFrame& frame, const RectF& dest, - const glm::vec4 tint, const bool alphaVideo) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawVideoTexture() called before BeginFrame()\n"); - return; - } - - EnsureMode(PipelineYUVFrame); - - VkDescriptorImageInfo imageBufferInfo[3]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = VideoFrameInternalYUV->LumaImage.ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageBufferInfo[1].sampler = Sampler; - imageBufferInfo[1].imageView = VideoFrameInternalYUV->CbImage.ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageBufferInfo[2].sampler = Sampler; - imageBufferInfo[2].imageView = VideoFrameInternalYUV->CrImage.ImageView; - imageBufferInfo[2].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 3; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineYUVFrame->PipelineLayout, 0, 1, &writeDescriptorSet); - - YUVFramePushConstants constants = {}; - constants.IsAlpha = alphaVideo; - vkCmdPushConstants(CommandBuffers[CurrentFrameIndex], - CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, - sizeof(YUVFramePushConstants), &constants); - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(RectF(0.0f, 0.0f, frame.Width, frame.Height), - {frame.Width, frame.Height}, &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tint; -} - -void Renderer::DrawVideoTexture(const NV12Frame& frame, const RectF& dest, - const glm::vec4 tint, const bool alphaVideo) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->DrawVideoTexture() called before BeginFrame()\n"); - return; - } - - EnsureMode(PipelineNV12Frame); - - VkDescriptorImageInfo imageBufferInfo[2]; - imageBufferInfo[0].sampler = Sampler; - imageBufferInfo[0].imageView = VideoFrameInternalNV12->LumaImage.ImageView; - imageBufferInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - imageBufferInfo[1].sampler = Sampler; - imageBufferInfo[1].imageView = VideoFrameInternalNV12->CbCrImage.ImageView; - imageBufferInfo[1].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkWriteDescriptorSet writeDescriptorSet{}; - writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeDescriptorSet.dstSet = 0; - writeDescriptorSet.dstBinding = 0; - writeDescriptorSet.descriptorCount = 2; - writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writeDescriptorSet.pImageInfo = imageBufferInfo; - - vkCmdPushDescriptorSetKHR( - CommandBuffers[CurrentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, - PipelineNV12Frame->PipelineLayout, 0, 1, &writeDescriptorSet); - - YUVFramePushConstants constants = {}; - constants.IsAlpha = alphaVideo; - vkCmdPushConstants(CommandBuffers[CurrentFrameIndex], - CurrentPipeline->PipelineLayout, - VK_SHADER_STAGE_FRAGMENT_BIT, 0, - sizeof(YUVFramePushConstants), &constants); - - // OK, all good, make quad - MakeQuad(); - - VertexBufferSprites* vertices = - (VertexBufferSprites*)(VertexBuffer + VertexBufferOffset + - VertexBufferFill); - VertexBufferFill += 4 * sizeof(VertexBufferSprites); - - QuadSetUV(RectF(0.0f, 0.0f, frame.Width, frame.Height), - {frame.Width, frame.Height}, &vertices[0].UV, - sizeof(VertexBufferSprites)); - QuadSetPosition(dest, &vertices[0].Position, sizeof(VertexBufferSprites)); - - for (int i = 0; i < 4; i++) vertices[i].Tint = tint; -} - -void Renderer::CaptureScreencap(Sprite& sprite) { - if (Textures.count(sprite.Sheet.Texture) == 0) return; - sprite.Sheet.IsScreenCap = true; - - sprite.Sheet.DesignWidth = static_cast(SwapChainExtent.width); - sprite.Sheet.DesignHeight = static_cast(SwapChainExtent.height); - sprite.Bounds.Width = sprite.Sheet.DesignWidth; - sprite.Bounds.Height = sprite.Sheet.DesignHeight; - sprite.BaseScale = {Profile::Game::DesignWidth / SwapChainExtent.width, - Profile::Game::DesignHeight / SwapChainExtent.height}; - - // Here we go... - Flush(); - vkCmdEndRenderPass(CommandBuffers[CurrentFrameIndex]); - - // Capture here - VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - - VkImageMemoryBarrier imageBarrierToTransfer = {}; - imageBarrierToTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToTransfer.image = Textures[sprite.Sheet.Texture].Image.Image; - imageBarrierToTransfer.subresourceRange = range; - imageBarrierToTransfer.srcAccessMask = 0; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - vkCmdPipelineBarrier(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - imageBarrierToTransfer.image = SwapChainImages[CurrentFrameIndex]; - imageBarrierToTransfer.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - vkCmdPipelineBarrier(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - VkOffset3D blitSize; - blitSize.x = SwapChainExtent.width; - blitSize.y = SwapChainExtent.height; - blitSize.z = 1; - VkImageBlit imageBlitRegion{}; - imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlitRegion.srcSubresource.layerCount = 1; - imageBlitRegion.srcOffsets[1] = blitSize; - imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageBlitRegion.dstSubresource.layerCount = 1; - imageBlitRegion.dstOffsets[1] = blitSize; - - vkCmdBlitImage(CommandBuffers[CurrentFrameIndex], - SwapChainImages[CurrentFrameIndex], - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - Textures[sprite.Sheet.Texture].Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlitRegion, - VK_FILTER_LINEAR); - - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageBarrierToTransfer.image = Textures[sprite.Sheet.Texture].Image.Image; - imageBarrierToTransfer.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - vkCmdPipelineBarrier(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imageBarrierToTransfer.image = SwapChainImages[CurrentFrameIndex]; - imageBarrierToTransfer.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - vkCmdPipelineBarrier(CommandBuffers[CurrentFrameIndex], - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = RenderPass; - renderPassInfo.framebuffer = SwapChainFramebuffers[CurrentImageIndex]; - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = SwapChainExtent; - renderPassInfo.clearValueCount = 0; - - vkCmdBeginRenderPass(CommandBuffers[CurrentFrameIndex], &renderPassInfo, - VK_SUBPASS_CONTENTS_INLINE); -} - -int Renderer::GetSpriteSheetImage(SpriteSheet const& sheet, - std::span outBuffer) { - const size_t bufferSize = - static_cast(sheet.DesignWidth * sheet.DesignHeight * 4); - assert(outBuffer.size() >= bufferSize); - - // Create a staging buffer to copy the image data to - AllocatedBuffer stagingBuffer = CreateBuffer( - bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY); - - // Transition the image layout to VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL - VkImageSubresourceRange subresourceRange = {}; - subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; - subresourceRange.baseArrayLayer = 0; - subresourceRange.layerCount = 1; - - ImmediateSubmit([&](VkCommandBuffer cmd) { - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.image = Textures[sheet.Texture].Image.Image; - barrier.subresourceRange = subresourceRange; - barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &barrier); - - // Copy the image to the staging buffer - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = 0; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = 0; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = 1; - copyRegion.imageOffset = {0, 0, 0}; - copyRegion.imageExtent = {static_cast(sheet.DesignWidth), - static_cast(sheet.DesignHeight), 1}; - - vkCmdCopyImageToBuffer(cmd, Textures[sheet.Texture].Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - stagingBuffer.Buffer, 1, ©Region); - - // Transition the image layout back to - // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &barrier); - }); - - // Map the staging buffer and copy the data to the output buffer - void* data; - vmaMapMemory(Allocator, stagingBuffer.Allocation, &data); - memcpy(outBuffer.data(), data, bufferSize); - vmaUnmapMemory(Allocator, stagingBuffer.Allocation); - - // Clean up the staging buffer - vmaDestroyBuffer(Allocator, stagingBuffer.Buffer, stagingBuffer.Allocation); - return static_cast(bufferSize); -} - -void Renderer::EnableScissor() {} - -void Renderer::SetScissorRect(RectF const& rect) { - if (rect.X != PreviousScissorRect.X && rect.Y != PreviousScissorRect.Y && - rect.Width != PreviousScissorRect.Width && - rect.Height != PreviousScissorRect.Height) { - float scale = - fmin((float)Window->WindowWidth / Profile::Game::DesignWidth, - (float)Window->WindowHeight / Profile::Game::DesignHeight); - float rectX = rect.X * scale; - float rectY = rect.Y * scale; - float rectWidth = rect.Width * scale; - float rectHeight = rect.Height * scale; - VkExtent2D scissorExtent; - scissorExtent.width = (int)(rectWidth); - scissorExtent.height = (int)(rectHeight); - VkRect2D scissor{}; - scissor.offset = {(int)rectX, (int)rectY}; - scissor.extent = scissorExtent; - Flush(); - vkCmdSetScissor(CommandBuffers[CurrentFrameIndex], 0, 1, &scissor); - PreviousScissorRect = rect; - } -} - -void Renderer::DisableScissor() { - if (PreviousScissorRect.X != 0.0f && PreviousScissorRect.Y != 0.0f && - PreviousScissorRect.Width != SwapChainExtent.width && - PreviousScissorRect.Height != SwapChainExtent.height) { - Flush(); - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = SwapChainExtent; - vkCmdSetScissor(CommandBuffers[CurrentFrameIndex], 0, 1, &scissor); - PreviousScissorRect = RectF(0.0f, 0.0f, (float)SwapChainExtent.width, - (float)SwapChainExtent.height); - } -} - -glm::vec2 Renderer::DesignToNDC(const glm::vec2 designCoord) const { - glm::vec2 result; - result.x = (designCoord.x / (Profile::Game::DesignWidth * 0.5f)) - 1.0f; - result.y = (designCoord.y / (Profile::Game::DesignHeight * 0.5f)) - 1.0f; - return result; -} - -void Renderer::Clear(glm::vec4 color) { - if (!Drawing) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Renderer->Clear() called before BeginFrame()\n"); - return; - } - - Flush(); - - VkClearAttachment clearAttachment = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .colorAttachment = 0, - .clearValue = - { - .color = {{color.r, color.g, color.b, color.a}}, - }, - }; - - VkClearRect clearRect = { - .rect = {.offset = {0, 0}, .extent = SwapChainExtent}, - .baseArrayLayer = 0, - .layerCount = 1}; - - vkCmdClearAttachments(CommandBuffers[CurrentFrameIndex], 1, &clearAttachment, - 1, &clearRect); -} - -} // namespace Vulkan -} // namespace Impacto diff --git a/src/renderer/vulkan/renderer.h b/src/renderer/vulkan/renderer.h deleted file mode 100644 index 5b35e1e76..000000000 --- a/src/renderer/vulkan/renderer.h +++ /dev/null @@ -1,276 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "../renderer.h" -#include "utils.h" -#include "window.h" -#include "yuvframe.h" -#include "nv12frame.h" - -namespace Impacto { -namespace Vulkan { - -const std::vector validationLayers = { - "VK_LAYER_KHRONOS_validation"}; - -#ifdef NDEBUG -const bool EnableValidationLayers = false; -#else -const bool EnableValidationLayers = true; -#endif - -struct SpritePushConstants { - VkBool32 IsInverted; - VkBool32 IsSameTexture; - glm::vec2 Alpha; -}; - -struct MaskedNoAlphaPushConstants { - glm::vec2 Alpha; - VkBool32 IsInverted; -}; - -struct YUVFramePushConstants { - VkBool32 IsAlpha; -}; - -struct CCBoxPushConstants { - glm::vec4 CCBoxAlpha; -}; - -class Renderer : public BaseRenderer { - public: - void RecreateSwapChain(); - - void Init() override; - void Shutdown() override; - -#ifndef IMPACTO_DISABLE_IMGUI - void ImGuiBeginFrame() override; -#endif - - void BeginFrame() override; - void BeginFrame2D() override; - void EndFrame() override; - - uint32_t MapSpriteSheet(SpriteSheet const& sheet) override { return 0; }; - bool LoadSurf(int surfId, int archiveId, int fileId) override { - return false; - }; - void UnloadSurf(int surfId) override {}; - uint32_t SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) override; - int GetSpriteSheetImage(SpriteSheet const& sheet, - std::span outBuffer) override; - void FreeTexture(uint32_t id) override; - YUVFrame* CreateYUVFrame(float width, float height) override; - NV12Frame* CreateNV12Frame(float width, float height) override; - - void DrawSprite(const Sprite& sprite, const CornersQuad& dest, - glm::mat4 transformation, std::span tints, - glm::vec3 colorShift, bool inverted, bool disableBlend, - bool textureWrapRepeat) override; - - void DrawMaskedSprite(const Sprite& sprite, const Sprite& mask, - const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, int fadeRange, - glm::mat4 spriteTransformation, - glm::mat4 maskTransformation, - std::span tints, bool isInverted, - bool isSameTexture) override; - - // TODO: implement - void DrawMaskedBinarySprite(const Sprite& sprite, const Sprite& mask, - const CornersQuad& spriteDest, - const CornersQuad& maskDest, - glm::mat4 spriteTransformation, - std::optional maskTransformation, - std::span tints, - bool isInverted) override {} - - void DrawMaskedSpriteOverlay(const Sprite& sprite, const Sprite& mask, - const CornersQuad& spriteDest, - const CornersQuad& maskDest, int alpha, - int fadeRange, glm::mat4 spriteTransformation, - glm::mat4 maskTransformation, - std::span tints, - bool isInverted, bool useMaskAlpha) override; - - void DrawPrimitives(const SpriteSheet& sheet, const SpriteSheet* mask, - ShaderProgramType shaderType, - std::span vertices, - std::span indices, - glm::mat4 spriteTransformation, - glm::mat4 maskTransformation, bool inverted, - TopologyMode topologyMode, - bool textureWrapRepeat = false) override; - - void DrawCCMessageBox(Sprite const& sprite, Sprite const& mask, - RectF const& dest, glm::vec4 tint, int alpha, - int fadeRange, float effectCt) override; - - void DrawEdgeDetectedSingleSheetFont( - const SpriteSheet& sheet, const SpriteSheet* mask, - std::span vertices, - std::span indices, float differenceFactor, - float intensityShift, float alphaShift, glm::vec2 renderScale, - glm::mat4 spriteTransformation, glm::mat4 maskTransformation) override { - } // TODO: Implement - - void DrawCHLCCMenuBackground(const Sprite& sprite, const Sprite& mask, - const RectF& dest, float alpha) override; - - void DrawBlurredSprite(const Sprite& sprite, const CornersQuad& dest, - glm::mat4 transformation, - RendererBlurDirection blurDirection, - glm::vec4 tint) override {}; // TODO: Implement - - void DrawMosaic(const Sprite& sprite, const CornersQuad dest, float tileSize, - glm::mat4 transformation, - glm::vec4 tint) override {}; // TODO: Implement - - void DrawVideoTexture(const YUVFrame& frame, const RectF& dest, - glm::vec4 tint, bool alphaVideo) override; - void DrawVideoTexture(const NV12Frame& frame, const RectF& dest, - glm::vec4 tint, bool alphaVideo = false) override; - void DrawSubtitleGlyph(const Sprite& sprite, const CornersQuad& dest, - const glm::mat4 transformation, - const glm::vec4 tint) override {}; // TODO: Implement - - void CaptureScreencap(Sprite& sprite) override; - - void SetFramebuffer(size_t buffer) override {}; // TODO: Implement - int GetFramebufferTexture(size_t buffer) override { - return 0; - }; // TODO: Implement - - void EnableScissor() override; - void SetScissorRect(RectF const& rect) override; - void DisableScissor() override; - - void SetStencilMode(StencilBufferMode mode) override {}; // TODO: implement - void ClearStencilBuffer() override {}; // TODO: implement - - void SetBlendMode(RendererBlendMode blendMode) override { - }; // TODO: Implement - - void Clear(glm::vec4 color) override; - - private: - void CreateInstance(); - void SetupDebug(); - void PickPhysicalDevice(); - void CreateLogicalDevice(); - void FindQueues(); - void CreateSurface(); - void CreateSwapChain(); - void CreateImageViews(); - void CreateRenderPass(); - void CreateFramebuffers(); - void CreateCommandPool(); - void CreateColorAndDepthImage(); - void CreateCommandBuffer(); - void CreateSyncObjects(); - void CreateDescriptors(); - - void CreateVertexBuffer(); - void CreateIndexBuffer(); - - void CleanupSwapChain(); - - void EnsureTextureBound(unsigned int texture); - void EnsureMode(Pipeline* pipeline, bool flush = true); - void Flush() override; - - void MakeQuad(); - - glm::vec2 DesignToNDC(glm::vec2 designCoord) const override; - - bool Drawing = false; - - VulkanWindow* VkWindow; - - VkDebugUtilsMessengerEXT DebugMessenger; - - VkInstance Instance; - VkPhysicalDevice PhysicalDevice; - VkDevice Device; - VkQueueFamilies QueueIndices; - VkQueue GraphicsQueue; - VkQueue PresentQueue; - - VkSurfaceKHR Surface; - - VkSwapchainKHR SwapChain; - std::vector SwapChainImages; - VkFormat SwapChainImageFormat; - VkExtent2D SwapChainExtent; - std::vector SwapChainImageViews; - std::vector SwapChainFramebuffers; - - AllocatedImage ColorImage; - VkImageView ColorImageView; - AllocatedImage DepthImage; - VkImageView DepthImageView; - - VkRenderPass RenderPass; - - VkCommandPool CommandPool; - VkCommandBuffer CommandBuffers[MAX_FRAMES_IN_FLIGHT]; - - VkSemaphore ImageAvailableSemaphores[MAX_FRAMES_IN_FLIGHT]; - VkSemaphore RenderFinishedSemaphores[MAX_FRAMES_IN_FLIGHT]; - VkFence InFlightFences[MAX_FRAMES_IN_FLIGHT]; - - VkDescriptorPool DescriptorPool; - VkDescriptorSetLayout SingleTextureSetLayout; - VkDescriptorSetLayout DoubleTextureSetLayout; - VkDescriptorSetLayout TripleTextureSetLayout; - - Pipeline* PipelineSprite; - Pipeline* PipelineSpriteNoBlending; - Pipeline* PipelineSpriteInverted; - Pipeline* PipelineMaskedSprite; - Pipeline* PipelineMaskedSpriteNoAlpha; - Pipeline* PipelineYUVFrame; - Pipeline* PipelineNV12Frame; - Pipeline* PipelineCCMessageBox; - Pipeline* PipelineCHLCCMenuBackground; - - AllocatedBuffer VertexBufferAlloc; - AllocatedBuffer IndexBufferAlloc; - - uint32_t CurrentTexture = 0; - uint32_t NextTextureId = 1; - - VkYUVFrame* VideoFrameInternalYUV; - VkNV12Frame* VideoFrameInternalNV12; - - static int constexpr VertexBufferSize = 4096 * 4096; - static int constexpr IndexBufferCount = - VertexBufferSize / (4 * sizeof(VertexBufferSprites)) * 6; - - uint8_t* VertexBuffer; - uint16_t* IndexBuffer; - - size_t VertexBufferFill = 0; - size_t VertexBufferOffset = 0; - size_t VertexBufferCount = 0; - size_t IndexBufferFill = 0; - size_t IndexBufferOffset = 0; - - RectF PreviousScissorRect; - - static VkVertexInputBindingDescription GetBindingDescription(); - - static std::array - GetAttributeDescriptions(); -}; - -inline Renderer* MainRendererInstance; - -} // namespace Vulkan -} // namespace Impacto diff --git a/src/renderer/vulkan/utils.cpp b/src/renderer/vulkan/utils.cpp deleted file mode 100644 index a02196e90..000000000 --- a/src/renderer/vulkan/utils.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "utils.h" - -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 -#define VMA_IMPLEMENTATION -#include - -namespace Impacto { -namespace Vulkan { - -void CreateAllocator(VkPhysicalDevice physicalDevice, VkDevice device, - VkInstance instance) { - VmaAllocatorCreateInfo allocatorInfo = {}; - VmaVulkanFunctions func = {}; - func.vkGetInstanceProcAddr = vkGetInstanceProcAddr; - func.vkGetDeviceProcAddr = vkGetDeviceProcAddr; - allocatorInfo.pVulkanFunctions = &func; - allocatorInfo.physicalDevice = physicalDevice; - allocatorInfo.device = device; - allocatorInfo.instance = instance; - vmaCreateAllocator(&allocatorInfo, &Allocator); -} - -AllocatedBuffer CreateBuffer(size_t allocSize, VkBufferUsageFlags usage, - VmaMemoryUsage memoryUsage) { - // allocate vertex buffer - VkBufferCreateInfo bufferInfo = {}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.pNext = nullptr; - bufferInfo.size = allocSize; - bufferInfo.usage = usage; - VmaAllocationCreateInfo vmaallocInfo = {}; - vmaallocInfo.usage = memoryUsage; - - AllocatedBuffer newBuffer; - - // allocate the buffer - vmaCreateBuffer(Allocator, &bufferInfo, &vmaallocInfo, &newBuffer.Buffer, - &newBuffer.Allocation, nullptr); - - return newBuffer; -} - -void ImmediateSubmit(std::function&& function) { - VkCommandBuffer cmd = MainUploadContext.CommandBuffer; - VkCommandBufferBeginInfo cmdBeginInfo = {}; - cmdBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmdBeginInfo.pNext = nullptr; - cmdBeginInfo.pInheritanceInfo = nullptr; - cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - - vkResetFences(MainUploadContext.Device, 1, &MainUploadContext.UploadFence); - - vkBeginCommandBuffer(cmd, &cmdBeginInfo); - function(cmd); - vkEndCommandBuffer(cmd); - - VkSubmitInfo submit = {}; - submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit.pNext = nullptr; - submit.waitSemaphoreCount = 0; - submit.pWaitSemaphores = nullptr; - submit.pWaitDstStageMask = nullptr; - submit.commandBufferCount = 1; - submit.pCommandBuffers = &MainUploadContext.CommandBuffer; - submit.signalSemaphoreCount = 0; - submit.pSignalSemaphores = nullptr; - vkQueueSubmit(MainUploadContext.GraphicsQueue, 1, &submit, - MainUploadContext.UploadFence); - - vkWaitForFences(MainUploadContext.Device, 1, &MainUploadContext.UploadFence, - true, UINT64_MAX); - vkResetFences(MainUploadContext.Device, 1, &MainUploadContext.UploadFence); - - vkResetCommandPool(MainUploadContext.Device, MainUploadContext.CommandPool, - 0); -} - -VkImageCreateInfo GetImageCreateInfo(VkFormat format, VkExtent3D extent, - VkSampleCountFlagBits msaaCount) { - VkImageCreateInfo dimgInfo = {}; - dimgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - dimgInfo.pNext = nullptr; - dimgInfo.imageType = VK_IMAGE_TYPE_2D; - dimgInfo.format = format; - dimgInfo.extent = extent; - dimgInfo.mipLevels = 1; - dimgInfo.arrayLayers = 1; - dimgInfo.samples = msaaCount; - dimgInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - dimgInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - return dimgInfo; -} - -} // namespace Vulkan -} // namespace Impacto diff --git a/src/renderer/vulkan/utils.h b/src/renderer/vulkan/utils.h deleted file mode 100644 index 7877a10d2..000000000 --- a/src/renderer/vulkan/utils.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "pipeline.h" - -namespace Impacto { -namespace Vulkan { - -int constexpr MAX_FRAMES_IN_FLIGHT = 2; - -inline uint32_t CurrentFrameIndex = 0; -inline uint32_t CurrentImageIndex = 0; - -inline Pipeline* CurrentPipeline = nullptr; - -inline VkSampler Sampler; - -inline PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR; - -struct VkQueueFamilies { - uint32_t GraphicsQueueIdx; - uint32_t PresentQueueIdx; -}; - -struct AllocatedBuffer { - VkBuffer Buffer; - VmaAllocation Allocation; -}; - -struct AllocatedImage { - VkImage Image; - VmaAllocation Allocation; -}; - -typedef struct VkTexture { - AllocatedImage Image; - VkImageView ImageView; - VkDescriptorSet Descriptor; -} VkTexture; - -inline ankerl::unordered_dense::map Textures; - -struct UploadContext { - VkDevice Device; - VkQueue GraphicsQueue; - VkFence UploadFence; - VkCommandPool CommandPool; - alignas(16) VkCommandBuffer CommandBuffer; -}; - -inline VmaAllocator Allocator; -inline UploadContext MainUploadContext; - -void CreateAllocator(VkPhysicalDevice physicalDevice, VkDevice device, - VkInstance instance); - -AllocatedBuffer CreateBuffer(size_t allocSize, VkBufferUsageFlags usage, - VmaMemoryUsage memoryUsage); - -void ImmediateSubmit(std::function&& function); - -VkImageCreateInfo GetImageCreateInfo(VkFormat format, VkExtent3D extent, - VkSampleCountFlagBits msaaCount); - -} // namespace Vulkan -} // namespace Impacto diff --git a/src/renderer/vulkan/window.cpp b/src/renderer/vulkan/window.cpp deleted file mode 100644 index 213504688..000000000 --- a/src/renderer/vulkan/window.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "window.h" - -#include - -#include "../renderer.h" -#include "../../log.h" -#include "../../profile/game.h" -#include "../../profile/profile.h" -#include "../../userconfig.h" -#include "../../game.h" - -#include "renderer.h" - -namespace Impacto { -namespace Vulkan { - -void VulkanWindow::UpdateDimensions() { - WindowDimensionsChanged = false; - SDL_GetWindowSizeInPixels(SDLWindow, &WindowWidth, &WindowHeight); - if (WindowWidth != lastWidth || WindowHeight != lastHeight || - MsaaCount != lastMsaa || RenderScale != lastRenderScale) { - WindowDimensionsChanged = true; - ImpLog(LogLevel::Debug, LogChannel::General, - "Drawable size (pixels): {:d} x {:d} ({:d}x MSAA requested, render " - "scale {:f})\n", - WindowWidth, WindowHeight, MsaaCount, RenderScale); - } - lastWidth = WindowWidth; - lastHeight = WindowHeight; - lastMsaa = MsaaCount; - lastRenderScale = RenderScale; - - DpiScale = SDL_GetWindowDisplayScale(SDLWindow); - // SDL_SetWindowInputFocus(SDLWindow); - MainRendererInstance->RecreateSwapChain(); -} - -void VulkanWindow::Init() { - assert(IsInit == false); - ImpLog(LogLevel::Info, LogChannel::General, "Creating window\n"); - IsInit = true; - -#ifdef __ANDROID__ - SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); -#endif - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "SDL initialisation failed: {:s}\n", SDL_GetError()); - Shutdown(); - return; - } - - SDL_WindowFlags windowFlags = SDL_WINDOW_VULKAN; - CreateSDLWindow(windowFlags); -} - -void VulkanWindow::SetDimensions(int width, int height, int msaa, - float renderScale) {} - -void VulkanWindow::SwapRTs() {} - -void VulkanWindow::Update() {} - -void VulkanWindow::Draw() { -#ifndef IMPACTO_DISABLE_IMGUI - if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } -#endif -} - -void VulkanWindow::Shutdown() { - SDL_DestroyWindow(SDLWindow); - SDL_Quit(); - // TODO move exit to users - exit(0); -} - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/window.h b/src/renderer/vulkan/window.h deleted file mode 100644 index 6940da0f7..000000000 --- a/src/renderer/vulkan/window.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "../window.h" - -namespace Impacto { -namespace Vulkan { - -class VulkanWindow : public BaseWindow { - public: - void Init() override; - void SetDimensions(int width, int height, int msaa, - float renderScale) override; - void SwapRTs() override; - void Update() override; - void Draw() override; - void Shutdown() override; - - private: - void UpdateDimensions() override; -}; - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/yuvframe.cpp b/src/renderer/vulkan/yuvframe.cpp deleted file mode 100644 index 2fa0fa0b5..000000000 --- a/src/renderer/vulkan/yuvframe.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "yuvframe.h" - -namespace Impacto { -namespace Vulkan { - -void VkYUVFrame::Init(float width, float height) { - Width = width; - Height = height; - - VkDeviceSize imageSize = (VkDeviceSize)(width * height); - VkDeviceSize bufferSize = - imageSize + 2 * (((VkDeviceSize)width / 2) * ((VkDeviceSize)height / 2)); - VkFormat imageFormat = VK_FORMAT_R8_UNORM; - - StagingBuffer = CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VMA_MEMORY_USAGE_CPU_ONLY); - vmaMapMemory(Allocator, StagingBuffer.Allocation, &MappedStagingBuffer); - - VkExtent3D lumaImageExtent; - lumaImageExtent.width = static_cast(width); - lumaImageExtent.height = static_cast(height); - lumaImageExtent.depth = 1; - - VkExtent3D cbCrImageExtent; - cbCrImageExtent.width = static_cast(width / 2); - cbCrImageExtent.height = static_cast(height / 2); - cbCrImageExtent.depth = 1; - - auto lumaImageInfo = - GetImageCreateInfo(imageFormat, lumaImageExtent, - VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT); - VmaAllocationCreateInfo dimgAllocinfo = {}; - dimgAllocinfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - vmaCreateImage(Allocator, &lumaImageInfo, &dimgAllocinfo, - &LumaImage.Image.Image, &LumaImage.Image.Allocation, nullptr); - - auto cbImageInfo = - GetImageCreateInfo(imageFormat, cbCrImageExtent, - VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT); - vmaCreateImage(Allocator, &cbImageInfo, &dimgAllocinfo, &CbImage.Image.Image, - &CbImage.Image.Allocation, nullptr); - - auto crImageInfo = - GetImageCreateInfo(imageFormat, cbCrImageExtent, - VkSampleCountFlagBits::VK_SAMPLE_COUNT_1_BIT); - vmaCreateImage(Allocator, &crImageInfo, &dimgAllocinfo, &CrImage.Image.Image, - &CrImage.Image.Allocation, nullptr); - - VkImageViewCreateInfo imageInfo = {}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageInfo.pNext = nullptr; - imageInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - imageInfo.image = LumaImage.Image.Image; - imageInfo.format = imageFormat; - imageInfo.subresourceRange.baseMipLevel = 0; - imageInfo.subresourceRange.levelCount = 1; - imageInfo.subresourceRange.baseArrayLayer = 0; - imageInfo.subresourceRange.layerCount = 1; - imageInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - vkCreateImageView(MainUploadContext.Device, &imageInfo, nullptr, - &LumaImage.ImageView); - - imageInfo.image = CbImage.Image.Image; - vkCreateImageView(MainUploadContext.Device, &imageInfo, nullptr, - &CbImage.ImageView); - - imageInfo.image = CrImage.Image.Image; - vkCreateImageView(MainUploadContext.Device, &imageInfo, nullptr, - &CrImage.ImageView); -} - -void VkYUVFrame::Submit(const void* luma, const void* cb, const void* cr) { - int cbOffset = (int)(Width * Height); - int crOffset = (int)((Width * Height) + ((Width / 2) * (Height / 2))); - - uint8_t* mappedStagingBuffer = (uint8_t*)MappedStagingBuffer; - - memcpy(mappedStagingBuffer, luma, cbOffset); - memcpy(mappedStagingBuffer + cbOffset, cb, - (size_t)((Width / 2) * (Height / 2))); - memcpy(mappedStagingBuffer + crOffset, cr, - (size_t)((Width / 2) * (Height / 2))); - - ImmediateSubmit([&](VkCommandBuffer cmd) { - VkExtent3D lumaImageExtent; - lumaImageExtent.width = static_cast(Width); - lumaImageExtent.height = static_cast(Height); - lumaImageExtent.depth = 1; - VkExtent3D cbCrImageExtent; - cbCrImageExtent.width = static_cast(Width / 2); - cbCrImageExtent.height = static_cast(Height / 2); - cbCrImageExtent.depth = 1; - - VkImageSubresourceRange range; - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - range.baseMipLevel = 0; - range.levelCount = 1; - range.baseArrayLayer = 0; - range.layerCount = 1; - - VkImageMemoryBarrier imageBarrierToTransfer = {}; - imageBarrierToTransfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - imageBarrierToTransfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - imageBarrierToTransfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToTransfer.image = LumaImage.Image.Image; - imageBarrierToTransfer.subresourceRange = range; - imageBarrierToTransfer.srcAccessMask = 0; - imageBarrierToTransfer.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = 0; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.imageSubresource.mipLevel = 0; - copyRegion.imageSubresource.baseArrayLayer = 0; - copyRegion.imageSubresource.layerCount = 1; - copyRegion.imageExtent = lumaImageExtent; - vkCmdCopyBufferToImage(cmd, StagingBuffer.Buffer, LumaImage.Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); - - VkImageMemoryBarrier imageBarrierToReadable = imageBarrierToTransfer; - imageBarrierToReadable.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageBarrierToReadable.newLayout = VK_IMAGE_LAYOUT_GENERAL; - imageBarrierToReadable.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageBarrierToReadable.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &imageBarrierToReadable); - - imageBarrierToTransfer.image = CbImage.Image.Image; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - copyRegion.bufferOffset = (VkDeviceSize)(Width * Height); - copyRegion.imageExtent = cbCrImageExtent; - vkCmdCopyBufferToImage(cmd, StagingBuffer.Buffer, CbImage.Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); - - imageBarrierToReadable.image = CbImage.Image.Image; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &imageBarrierToReadable); - - imageBarrierToTransfer.image = CrImage.Image.Image; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, - nullptr, 1, &imageBarrierToTransfer); - - copyRegion.bufferOffset = crOffset; - vkCmdCopyBufferToImage(cmd, StagingBuffer.Buffer, CrImage.Image.Image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - ©Region); - - imageBarrierToReadable.image = CrImage.Image.Image; - vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, - 0, nullptr, 1, &imageBarrierToReadable); - }); -} - -void VkYUVFrame::Release() { - vmaUnmapMemory(Allocator, StagingBuffer.Allocation); -} - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/vulkan/yuvframe.h b/src/renderer/vulkan/yuvframe.h deleted file mode 100644 index 615060b93..000000000 --- a/src/renderer/vulkan/yuvframe.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "../yuvframe.h" -#include "utils.h" - -#include - -namespace Impacto { -namespace Vulkan { - -class VkYUVFrame : public YUVFrame { - friend class Renderer; - - public: - void Init(float width, float height) override; - - void Submit(const void* luma, const void* cb, const void* cr) override; - void Release() override; - - protected: - VkTexture LumaImage{}; - VkTexture CbImage{}; - VkTexture CrImage{}; - - private: - AllocatedBuffer StagingBuffer; - void* MappedStagingBuffer; -}; - -} // namespace Vulkan -} // namespace Impacto \ No newline at end of file diff --git a/src/renderer/window.cpp b/src/renderer/window.cpp index 216f931f1..d4d8604e4 100644 --- a/src/renderer/window.cpp +++ b/src/renderer/window.cpp @@ -10,8 +10,6 @@ #include #include "../inputsystem.h" #include "opengl/window.h" -#include "vulkan/window.h" -#include "dx9/window.h" namespace Impacto { @@ -21,16 +19,6 @@ void InitWindow() { case RendererType::OpenGL: Window = new OpenGL::GLWindow(); break; -#endif -#ifndef IMPACTO_DISABLE_VULKAN - case RendererType::Vulkan: - Window = new Vulkan::VulkanWindow(); - break; -#endif -#ifndef IMPACTO_DISABLE_DX9 - case RendererType::DirectX9: - Window = new DirectX9::DirectX9Window(); - break; #endif default: ImpLog(LogLevel::Error, LogChannel::Render, diff --git a/src/shaders/dx9/CCMessageBoxSprite_frag.hlsl b/src/shaders/dx9/CCMessageBoxSprite_frag.hlsl deleted file mode 100644 index 0f259760d..000000000 --- a/src/shaders/dx9/CCMessageBoxSprite_frag.hlsl +++ /dev/null @@ -1,36 +0,0 @@ -float4 Alpha : register(c0); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler ColorMap : register(s0); -sampler Mask : register(s1); - -float4 main(PS_INPUT input) : COLOR { - float4 color = tex2D(ColorMap, input.uv); - color *= input.tint; - float4 alp = tex2D(Mask, input.maskUV); - float ga = alp.r; - float ea = 1.0 - alp.g; - float fa = 1.0 - alp.b; - fa *= Alpha.r; - fa -= Alpha.g; - fa = clamp(fa, 0.0, 1.0); - color.a *= fa; - - ea += Alpha.b; - if (ea > 1.0) ea = 2.0 - ea; - ea *= 2.0; - if (ea > 1.0) ea = 2.0 - ea; - - ga *= ea; - ga = clamp(ga, 0.0, 1.0); - color.a -= ga; - color.a = clamp(color.a, 0.0, 1.0); - - return color; -} diff --git a/src/shaders/dx9/CCMessageBoxSprite_vert.hlsl b/src/shaders/dx9/CCMessageBoxSprite_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/CCMessageBoxSprite_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/CHLCCMenuBackground_frag.hlsl b/src/shaders/dx9/CHLCCMenuBackground_frag.hlsl deleted file mode 100644 index eb5fc2bb8..000000000 --- a/src/shaders/dx9/CHLCCMenuBackground_frag.hlsl +++ /dev/null @@ -1,32 +0,0 @@ -float4 Alpha : register(c0); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler ColorMap : register(s0); -sampler Mask : register(s1); - -float remapMiddle(float value, float newMiddle) { - if (value < 0.5) { - return lerp(0.0, newMiddle, 2.0 * value); - } else { - return lerp(newMiddle, 1.0, 2.0 * value - 1.0); - } -} - -float4 main(PS_INPUT input) : COLOR { - float4 color = tex2D(ColorMap, input.uv); - float4 mask = tex2D(Mask, input.maskUV); - float4 outColor = float4( - remapMiddle(color.r, mask.r), - remapMiddle(color.g, mask.g), - remapMiddle(color.b, mask.b), - mask.a * Alpha.r - ); - - return outColor; -} diff --git a/src/shaders/dx9/CHLCCMenuBackground_vert.hlsl b/src/shaders/dx9/CHLCCMenuBackground_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/CHLCCMenuBackground_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/MaskedSpriteNoAlpha_frag.hlsl b/src/shaders/dx9/MaskedSpriteNoAlpha_frag.hlsl deleted file mode 100644 index 240aecca1..000000000 --- a/src/shaders/dx9/MaskedSpriteNoAlpha_frag.hlsl +++ /dev/null @@ -1,32 +0,0 @@ -float2 Alpha : register(c0); -bool IsInverted : register(b0); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler ColorMap : register(s0); -sampler Mask : register(s1); - -float rgbToLightness(float3 rgb) { - float maxVal = max(max(rgb.r, rgb.g), rgb.b); - float minVal = min(min(rgb.r, rgb.g), rgb.b); - - return (maxVal + minVal) / 2.0; -} - -float4 main(PS_INPUT input) : COLOR { - float4 color = tex2D(ColorMap, input.uv); - float4 alp = tex2D(Mask, input.maskUV); - float maskAlpha = rgbToLightness(alp.rgb); - if (IsInverted) maskAlpha = 1.0f - maskAlpha; - maskAlpha *= Alpha.x; - maskAlpha -= Alpha.y; - maskAlpha = clamp(maskAlpha, 0.0, 1.0); - color *= input.tint; - color.a *= maskAlpha; - return color; -} diff --git a/src/shaders/dx9/MaskedSpriteNoAlpha_vert.hlsl b/src/shaders/dx9/MaskedSpriteNoAlpha_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/MaskedSpriteNoAlpha_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/MaskedSprite_frag.hlsl b/src/shaders/dx9/MaskedSprite_frag.hlsl deleted file mode 100644 index 2dfb0a644..000000000 --- a/src/shaders/dx9/MaskedSprite_frag.hlsl +++ /dev/null @@ -1,31 +0,0 @@ -float2 Alpha : register(c0); -bool IsInverted : register(b0); -bool IsSameTexture : register(b1); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler ColorMap : register(s0); -sampler Mask : register(s1); - -float4 main(PS_INPUT input) : COLOR { - float4 color = tex2D(ColorMap, input.uv); - float4 alp = tex2D(Mask, input.maskUV); - if (IsInverted) alp.a = 1.0f - alp.a; - alp.a *= Alpha.x; - alp.a -= Alpha.y; - alp.a = clamp(alp.a, 0.0, 1.0); - if (IsSameTexture) { - color.a = alp.a; - color.a *= input.tint.a; - } else { - color *= input.tint; - color.a *= alp.a; - } - - return color; -} diff --git a/src/shaders/dx9/MaskedSprite_vert.hlsl b/src/shaders/dx9/MaskedSprite_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/MaskedSprite_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/NV12Frame_frag.hlsl b/src/shaders/dx9/NV12Frame_frag.hlsl deleted file mode 100644 index 62cf89d8a..000000000 --- a/src/shaders/dx9/NV12Frame_frag.hlsl +++ /dev/null @@ -1,37 +0,0 @@ -bool IsAlpha : register(b0); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler Luma : register(s0); -sampler CbCr : register(s1); - -static float4x4 yuv_to_rgb_rec601 = { - 1.16438, 0.00000, 1.59603, -0.87079, 1.16438, -0.39176, -0.81297, 0.52959, - 1.16438, 2.01723, 0.00000, -1.08139, 0, 0, 0, 1}; - -float4 getRGBA(float2 texUv) { - float4 yuvcolor = {1.0, 1.0, 1.0, 1.0}; - yuvcolor.r = tex2D(Luma, texUv).a; - yuvcolor.gb = tex2D(CbCr, texUv).ra; - - return mul(yuv_to_rgb_rec601, yuvcolor); -} - -float4 main(PS_INPUT input) : COLOR { - float4 color = {1.0, 1.0, 1.0, 1.0}; - - if (IsAlpha) { - color = getRGBA(float2(input.uv.x, input.uv.y / 2.0)); - color.a = getRGBA(float2(input.uv.x, input.uv.y / 2.0 + 0.5)).a; - } else { - color = getRGBA(input.uv); - } - color *= input.tint; - - return color; -} diff --git a/src/shaders/dx9/NV12Frame_vert.hlsl b/src/shaders/dx9/NV12Frame_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/NV12Frame_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/Renderable3D_Background_frag.hlsl b/src/shaders/dx9/Renderable3D_Background_frag.hlsl deleted file mode 100644 index d82136241..000000000 --- a/src/shaders/dx9/Renderable3D_Background_frag.hlsl +++ /dev/null @@ -1,9 +0,0 @@ -struct PS_INPUT { - float2 uv : TEXCOORD0; -}; - -sampler ColorMap : register(s0); - -float4 main(PS_INPUT input) : COLOR { - return tex2D(ColorMap, input.uv); -} diff --git a/src/shaders/dx9/Renderable3D_Background_vert.hlsl b/src/shaders/dx9/Renderable3D_Background_vert.hlsl deleted file mode 100644 index fd1aa2be1..000000000 --- a/src/shaders/dx9/Renderable3D_Background_vert.hlsl +++ /dev/null @@ -1,20 +0,0 @@ -float4x4 MVP : register(c0); - -struct VS_INPUT { - float3 Position : POSITION; - float2 UV : TEXCOORD0; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = mul(MVP, float4(input.Position, 1.0)); - output.uv = input.UV; - - return output; -} diff --git a/src/shaders/dx9/Renderable3D_Character_frag.hlsl b/src/shaders/dx9/Renderable3D_Character_frag.hlsl deleted file mode 100644 index 11560e306..000000000 --- a/src/shaders/dx9/Renderable3D_Character_frag.hlsl +++ /dev/null @@ -1,108 +0,0 @@ -// Character3DScene -float4x4 ViewProjection : register(c0); -float4 Tint : register(c4); -float3 WorldLightPosition : register(c5); -float3 WorldEyePosition : register(c6); -bool DarkMode : register(b0); - -// Character3DModel -float4x4 Model : register(c7); - -// Character3DMesh -bool HasShadowColorMap : register(b1); -float ModelOpacity : register(c11); -float4x4 Bones[32] : register(c12); - -static const float FALLOFF_POWER = 0.8; - -static const float4 g_ToonFalloffGradVals = - float4(0.546875, 0.421875, 0.468750, 0.281250); -static const float4 g_ToonFalloffGradScale = - float4(10.66667, 10.66667, 32.0, 32.0); -static const float4 g_ToonFalloffGradDarkVals = - float4(0.59375, 0.484375, 0.609375, 0.453125); -static const float4 g_ToonFalloffGradDarkMax = float4(0.79, 0.79, 0.61, 0.61); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float3 worldFragPosition : TEXCOORD1; - float3 worldNormal : TEXCOORD2; -}; - -sampler ColorMap : register(s0); -sampler GradientMaskMap : register(s1); -sampler SpecularColorMap : register(s2); -sampler ShadowColorMap : register(s3); - -float4 main(PS_INPUT input) : COLOR { - float4 texColor = tex2D(ColorMap, input.uv); - float maskParam = tex2D(GradientMaskMap, input.uv).r; - float3 specColor = tex2D(SpecularColorMap, input.uv).rgb; - - float3 normal = normalize(input.worldNormal); - float3 dirToLight = normalize(WorldLightPosition - input.worldFragPosition); - float3 dirToEye = normalize(WorldEyePosition - input.worldFragPosition); - - float NdotL = dot(normal, dirToLight); - float scaledDiff = 0.5 * NdotL + 0.5; - - // Note: this is a uniform in R;NE ??? - float3 H = normalize(dirToLight + dirToEye); - - float4 toonFalloffGradInput; - toonFalloffGradInput.xy = (scaledDiff).xx; - - float normDotEye = 1.0 - dot(normal, dirToEye); - toonFalloffGradInput.zw = (scaledDiff * normDotEye).xx; - - // Original just uses step here but that looks bad - float4 toonFalloffGradParamDark = - smoothstep(g_ToonFalloffGradDarkVals * 0.95, - g_ToonFalloffGradDarkVals * 1.05, toonFalloffGradInput) * - g_ToonFalloffGradDarkMax; - - float4 toonFalloffGradParamLight = saturate( - (toonFalloffGradInput - g_ToonFalloffGradVals) * g_ToonFalloffGradScale); - - float4 toonFalloffGradParam; - if (DarkMode) { - toonFalloffGradParam = toonFalloffGradParamDark; - } else { - toonFalloffGradParam = toonFalloffGradParamLight; - } - - float2 toonFalloffInterpParam = - lerp(toonFalloffGradParam.xz, toonFalloffGradParam.yw, maskParam); - - float3 shadowColor; -#if defined(IsDaSH) - if (HasShadowColorMap) { - shadowColor = tex2D(ShadowColorMap, input.uv).rgb; - } else { -#endif - shadowColor = max(texColor.rgb, (0.5).xxx) * texColor.rgb; -#if IsDaSH - } -#endif - - float3 toonColor = lerp(shadowColor, texColor.rgb, toonFalloffInterpParam.x); - - // Tint - - float3 baseTintColor = toonColor * Tint.rgb; - toonColor = lerp(toonColor, baseTintColor, Tint.a); - - // Rimlight - - float3 falloffColor = FALLOFF_POWER * toonFalloffInterpParam.y * texColor.rgb; - toonColor += falloffColor * ((1.0).xxx - toonColor); - - // Specular - // R;NE does not use max() here - maybe manual control of H ensures it doesn't - // go negative? - float specIntensity = pow(max(dot(normal, H), 0.0), 20.0); - toonColor += specIntensity * specColor; - - return float4(toonColor, texColor.a * ModelOpacity); -} diff --git a/src/shaders/dx9/Renderable3D_Character_vert.hlsl b/src/shaders/dx9/Renderable3D_Character_vert.hlsl deleted file mode 100644 index ed7edf2a2..000000000 --- a/src/shaders/dx9/Renderable3D_Character_vert.hlsl +++ /dev/null @@ -1,53 +0,0 @@ -// Character3DScene -float4x4 ViewProjection : register(c0); -float4 Tint : register(c4); -float3 WorldLightPosition : register(c5); -float3 WorldEyePosition : register(c6); -bool DarkMode : register(b0); - -// Character3DModel -float4x4 Model : register(c7); - -// Character3DMesh -bool HasShadowColorMap : register(b1); -float ModelOpacity : register(c11); -float4x4 Bones[32] : register(c12); - -struct VS_INPUT { - float3 Position : POSITION; - float3 Normal : NORMAL; - float2 UV : TEXCOORD0; - uint4 BoneIndices : BLENDINDICES; - float4 BoneWeights : BLENDWEIGHT; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float3 worldFragPosition : TEXCOORD1; - float3 worldNormal : TEXCOORD2; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - // Accumulated skinning, thanks - // https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch04.html - float4x4 skeletalTransform = - mul(Bones[input.BoneIndices.x], input.BoneWeights.x) + - mul(Bones[input.BoneIndices.y], input.BoneWeights.y) + - mul(Bones[input.BoneIndices.z], input.BoneWeights.z) + - mul(Bones[input.BoneIndices.w], input.BoneWeights.w); - - float4x4 transform = mul(Model, skeletalTransform); - float3x3 normalMatrix = (float3x3)transform; - - float4 worldPosition = mul(transform, float4(input.Position, 1.0)); - output.worldFragPosition = worldPosition.xyz; - - output.position = mul(ViewProjection, worldPosition); - output.worldNormal = mul(normalMatrix, input.Normal); - output.uv = input.UV; - - return output; -} diff --git a/src/shaders/dx9/Renderable3D_Eye_frag.hlsl b/src/shaders/dx9/Renderable3D_Eye_frag.hlsl deleted file mode 100644 index 22e6fe383..000000000 --- a/src/shaders/dx9/Renderable3D_Eye_frag.hlsl +++ /dev/null @@ -1,53 +0,0 @@ -// Character3DScene -float4x4 ViewProjection : register(c0); -float4 Tint : register(c4); -float3 WorldLightPosition : register(c5); -float3 WorldEyePosition : register(c6); -bool DarkMode : register(b0); - -// Character3DModel -float4x4 Model : register(c7); - -// Character3DMesh -bool HasShadowColorMap : register(b1); -float ModelOpacity : register(c11); -float4x4 Bones[32] : register(c12); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; -}; - -static const float FALLOFF_POWER = 0.8; -static const float HIGHLIGHT_TINT_INTENSITY = 0.6; - -sampler IrisColorMap : register(s0); -sampler WhiteColorMap : register(s1); -sampler HighlightColorMap : register(s2); -sampler IrisSpecularColorMap : register(s3); - -float4 main(PS_INPUT input) : COLOR { - float4 eyeWhiteColor = tex2D(WhiteColorMap, input.uv); - float4 irisColor = tex2D(IrisColorMap, input.uv); - float4 highlightColor = tex2D(HighlightColorMap, input.uv); - - float3 eyeColor = lerp(eyeWhiteColor.rgb, irisColor.rgb, irisColor.a); - -#if !defined(IsDaSH) - // "Specular" - float4 irisSpecularColor = tex2D(IrisSpecularColorMap, input.uv); - eyeColor += irisSpecularColor.rgb * 0.1; -#endif - - // Tint - float3 baseTintColor = eyeColor * Tint.rgb; - eyeColor = lerp(eyeColor, baseTintColor, Tint.a); - - // Highlight - float3 highlightTintColor = highlightColor.rgb * Tint.rgb; - highlightColor.rgb = lerp(highlightColor.rgb, highlightTintColor, - HIGHLIGHT_TINT_INTENSITY * Tint.a); - eyeColor = lerp(eyeColor, highlightColor.rgb, highlightColor.a); - - return float4(eyeColor, ModelOpacity); -} diff --git a/src/shaders/dx9/Renderable3D_Eye_vert.hlsl b/src/shaders/dx9/Renderable3D_Eye_vert.hlsl deleted file mode 100644 index be05bf813..000000000 --- a/src/shaders/dx9/Renderable3D_Eye_vert.hlsl +++ /dev/null @@ -1,48 +0,0 @@ -// Character3DScene -float4x4 ViewProjection : register(c0); -float4 Tint : register(c4); -float3 WorldLightPosition : register(c5); -float3 WorldEyePosition : register(c6); -bool DarkMode : register(b0); - -// Character3DModel -float4x4 Model : register(c7); - -// Character3DMesh -bool HasShadowColorMap : register(b1); -float ModelOpacity : register(c11); -float4x4 Bones[32] : register(c12); - -struct VS_INPUT { - float3 Position : POSITION; - float3 Normal : NORMAL; - float2 UV : TEXCOORD0; - uint4 BoneIndices : BLENDINDICES; - float4 BoneWeights : BLENDWEIGHT; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - // Accumulated skinning, thanks - // https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch04.html - float4x4 skeletalTransform = - mul(Bones[input.BoneIndices.x], input.BoneWeights.x) + - mul(Bones[input.BoneIndices.y], input.BoneWeights.y) + - mul(Bones[input.BoneIndices.z], input.BoneWeights.z) + - mul(Bones[input.BoneIndices.w], input.BoneWeights.w); - - float4x4 transform = mul(Model, skeletalTransform); - - float4 worldPosition = mul(transform, float4(input.Position, 1.0)); - - output.position = mul(ViewProjection, worldPosition); - output.uv = input.UV; - - return output; -} diff --git a/src/shaders/dx9/Renderable3D_Outline_frag.hlsl b/src/shaders/dx9/Renderable3D_Outline_frag.hlsl deleted file mode 100644 index 9ba6ba4e4..000000000 --- a/src/shaders/dx9/Renderable3D_Outline_frag.hlsl +++ /dev/null @@ -1,52 +0,0 @@ -// Character3DScene -float4x4 ViewProjection : register(c0); -float4 Tint : register(c4); -float3 WorldLightPosition : register(c5); -float3 WorldEyePosition : register(c6); -bool DarkMode : register(b0); - -// Character3DModel -float4x4 Model : register(c7); - -// Character3DMesh -bool HasShadowColorMap : register(b1); -float ModelOpacity : register(c11); -float4x4 Bones[32] : register(c12); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float2 uvNoise : TEXCOORD1; -}; - -sampler ColorMap : register(s0); -sampler NoiseMap : register(s1); - -float4 main(PS_INPUT input) : COLOR { - float4 color; - float4 texColor = tex2D(ColorMap, input.uv); - if (texColor.a <= 0.1) discard; - -#if defined(IsDaSH) - float3 factor1 = (0.70588).xxx; - float3 factor2 = (8.0).xxx; - - float3 c1 = - factor1 * texColor.rgb + clamp(texColor.rgb * factor2, 0.0, 1.0) * 0.25; - // 0.4, 0.2, 0.2 is from mesh info unk9 - float3 c2 = clamp(c1 + vec3(0.4, 0.2, 0.2) + vec3(-1.0), 0.0, 1.0); - float3 c3 = -c1 + c2; - - float noiseFactor = tex2D(NoiseMap, input.uvNoise).r; - - color = float4(c3 * noiseFactor + c1, 1.0); -#else - static const float4 outlineColor = - float4(0.46484375, 0.27734375, 0.22265625, 1.0); - color = outlineColor * texColor; -#endif - - color.a *= ModelOpacity; - - return color; -} diff --git a/src/shaders/dx9/Renderable3D_Outline_vert.hlsl b/src/shaders/dx9/Renderable3D_Outline_vert.hlsl deleted file mode 100644 index 56ea6e319..000000000 --- a/src/shaders/dx9/Renderable3D_Outline_vert.hlsl +++ /dev/null @@ -1,69 +0,0 @@ -// Character3DScene -float4x4 ViewProjection : register(c0); -float4 Tint : register(c4); -float3 WorldLightPosition : register(c5); -float3 WorldEyePosition : register(c6); -bool DarkMode : register(b0); - -// Character3DModel -float4x4 Model : register(c7); - -// Character3DMesh -bool HasShadowColorMap : register(b1); -float ModelOpacity : register(c11); -float4x4 Bones[32] : register(c12); - -struct VS_INPUT { - float3 Position : POSITION; - float3 Normal : NORMAL; - float2 UV : TEXCOORD0; - uint4 BoneIndices : BLENDINDICES; - float4 BoneWeights : BLENDWEIGHT; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float3 uvNoise : TEXCOORD1; -}; - -// TODO there's a uniform for this somewhere... -#if defined(IsDaSH) -static const float OutlineThickness = 0.0035; -#else -static const float OutlineThickness = 0.035; -#endif - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - // Accumulated skinning, thanks - // https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch04.html - float4x4 skeletalTransform = - mul(Bones[input.BoneIndices.x], input.BoneWeights.x) + - mul(Bones[input.BoneIndices.y], input.BoneWeights.y) + - mul(Bones[input.BoneIndices.z], input.BoneWeights.z) + - mul(Bones[input.BoneIndices.w], input.BoneWeights.w); - - float4x4 transform = mul(Model, skeletalTransform); - float3x3 normalMatrix = (float3x3)transform; - - float3 worldNormal = mul(normalMatrix, input.Normal); - - float4 viewNormal = normalize(mul(ViewProjection, float4(worldNormal, 0.0))); - - float4 worldPosition = mul(transform, float4(input.Position, 1.0)); - - output.position = mul(ViewProjection, worldPosition); - output.position += viewNormal * OutlineThickness; - - output.uv = input.UV; - -#if defined(IsDaSH) - output.uvNoise = ((output.position.xy / output.position.w) * 0.2).xyy; -#else - output.uvNoise = (0.0).xxx; -#endif - - return output; -} diff --git a/src/shaders/dx9/Sprite_frag.hlsl b/src/shaders/dx9/Sprite_frag.hlsl deleted file mode 100644 index 5d4b63306..000000000 --- a/src/shaders/dx9/Sprite_frag.hlsl +++ /dev/null @@ -1,12 +0,0 @@ -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler ColorMap : register(s0); - -float4 main(PS_INPUT input) : COLOR { - return input.tint * tex2D(ColorMap, input.uv); -} diff --git a/src/shaders/dx9/Sprite_inverted_frag.hlsl b/src/shaders/dx9/Sprite_inverted_frag.hlsl deleted file mode 100644 index 149c58bfd..000000000 --- a/src/shaders/dx9/Sprite_inverted_frag.hlsl +++ /dev/null @@ -1,16 +0,0 @@ -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler ColorMap : register(s0); - -float4 main(PS_INPUT input) : COLOR { - float4 color = tex2D(ColorMap, input.uv); - color.r = 1.0 - color.r; - color.g = 1.0 - color.g; - color.b = 1.0 - color.b; - return input.tint * color; -} diff --git a/src/shaders/dx9/Sprite_inverted_vert.hlsl b/src/shaders/dx9/Sprite_inverted_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/Sprite_inverted_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/Sprite_vert.hlsl b/src/shaders/dx9/Sprite_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/Sprite_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/dx9/YUVFrame_frag.hlsl b/src/shaders/dx9/YUVFrame_frag.hlsl deleted file mode 100644 index 615b521dc..000000000 --- a/src/shaders/dx9/YUVFrame_frag.hlsl +++ /dev/null @@ -1,39 +0,0 @@ -bool IsAlpha : register(b0); - -struct PS_INPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -sampler Luma : register(s0); -sampler Cb : register(s1); -sampler Cr : register(s2); - -static float4x4 yuv_to_rgb_rec601 = { - 1.16438, 0.00000, 1.59603, -0.87079, 1.16438, -0.39176, -0.81297, 0.52959, - 1.16438, 2.01723, 0.00000, -1.08139, 0, 0, 0, 1}; - -float4 getRGBA(float2 texUv) { - float4 yuvcolor = {1.0, 1.0, 1.0, 1.0}; - yuvcolor.r = tex2D(Luma, texUv).a; - yuvcolor.g = tex2D(Cb, texUv).a; - yuvcolor.b = tex2D(Cr, texUv).a; - - return mul(yuv_to_rgb_rec601, yuvcolor); -} - -float4 main(PS_INPUT input) : COLOR { - float4 color = {1.0, 1.0, 1.0, 1.0}; - - if (IsAlpha) { - color = getRGBA(float2(input.uv.x, input.uv.y / 2.0)); - color.a = getRGBA(float2(input.uv.x, input.uv.y / 2.0 + 0.5)).a; - } else { - color = getRGBA(input.uv); - } - color *= input.tint; - - return color; -} diff --git a/src/shaders/dx9/YUVFrame_vert.hlsl b/src/shaders/dx9/YUVFrame_vert.hlsl deleted file mode 100644 index d1d297931..000000000 --- a/src/shaders/dx9/YUVFrame_vert.hlsl +++ /dev/null @@ -1,24 +0,0 @@ -struct VS_INPUT { - float2 Position : POSITION; - float2 UV : TEXCOORD0; - float4 Tint : COLOR; - float2 MaskUV : TEXCOORD1; -}; - -struct VS_OUTPUT { - float4 position : POSITION; - float2 uv : TEXCOORD0; - float4 tint : COLOR; - float2 maskUV : TEXCOORD1; -}; - -VS_OUTPUT main(VS_INPUT input) { - VS_OUTPUT output; - - output.position = float4(input.Position, 0.0, 1.0); - output.uv = input.UV; - output.tint = input.Tint; - output.maskUV = input.MaskUV; - - return output; -} diff --git a/src/shaders/vulkan/CCMessageBoxSprite_frag.glsl b/src/shaders/vulkan/CCMessageBoxSprite_frag.glsl deleted file mode 100644 index 4dcff32af..000000000 --- a/src/shaders/vulkan/CCMessageBoxSprite_frag.glsl +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec4 tint; -layout(location = 2) in vec2 maskUV; - -layout(location = 0) out vec4 color; - -layout(binding = 0) uniform sampler2D ColorMap[2]; - -layout(push_constant) uniform constants -{ - vec4 CCBoxAlpha; -} PushConstants; - -void main() { - color = texture(ColorMap[0], uv); - color *= tint; - vec4 alp = texture(ColorMap[1], maskUV); - float ga = alp.r; - float ea = 1.0 - alp.g; - float fa = 1.0 - alp.b; - fa *= PushConstants.CCBoxAlpha.r; - fa -= PushConstants.CCBoxAlpha.g; - fa = clamp(fa,0.0,1.0); - color.a *= fa; - - ea += PushConstants.CCBoxAlpha.b; - if (ea > 1.0) ea = 2.0 - ea; - ea *= 2.0; - if (ea > 1.0) ea = 2.0 - ea; - - ga *= ea; - ga = clamp(ga, 0.0, 1.0); - color.a -= ga; - color.a = clamp(color.a,0.0,1.0); -} \ No newline at end of file diff --git a/src/shaders/vulkan/CCMessageBoxSprite_frag.spv b/src/shaders/vulkan/CCMessageBoxSprite_frag.spv deleted file mode 100644 index 112580e10a6a05b6724222cbcf1ba7db597162f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2708 zcmZ9MYjaao6oz-{1I9gda zd+v-L+tXy>sLzfxo2J;6wPvTMVHSA}IgA`bcH*y{gFusHPw7vBr_$zBt2b)P%eDHo zMr$x=3`akA+l_9g*KVwIUbI`I&daubn=-#nuhm^&$sMNg$j?`|hE~7Zf5AS@-%j?b z`pxD52s2sKxc*W+Rn$7_^hRNu12nsX!sZ>;n#1S!zaGcEgZ`{J#;3vU5`PGOTHxvQ z5xCXw4M)x1Xb7I+PtH}XUhV(1)E%rAzBB1#xZCT))oSKnEAMcmh)7A@I~@I=K9}kC zJomT%>Jy0Z-b3B~-{59Z&pf)TMo;9l@8Q>du9(=E+Yg?Bs~`u+=RDQzeTCmm?7j^7 zi>2-yb$jMA z-!AqF;(6v%-;KD8-!q0qPVcuL-FiJw`vG=i<;|~d&*iiqDskLj-5G?v0@kL)`A5Op zBcC%0{}W(+ts(Az66{i!UnsO+u7v$PbmNcEOJ`}kwOwF$7IL1Y?z@xI{z-}BEcee4 zSLCjNou&RaO03^rI&_CUYT`3-EuQC%**o8d%h*>i)9ltzVV^^+QQiCcZRNV(SFZbw zsV|YmdF@4<@%SBD|;P_Ufrnlhaqo(6vXB{=Y4c15Aoc2Y|oc84uBIo?gVc*|HfwI| ztiSIe{ND%5|3*&ZKR|px^5(GDa*^XK*c^Uek>ea#K60D~n?v3l&PQ&E6MRz_5#O2f z$!q_#v_;-a=*HS(YrBld=@)tBBJUM&MH{iVPZ_(wV?k8ZEb!+<$ zk+W`br{S<3s-e>~|UWXo2PQGoLoO@LvJT#oKFxwRM#);&og_R-G!5ny4S!_x3;J| Qa`fQxGt`awm#7QKfA+1e-T(jq diff --git a/src/shaders/vulkan/CCMessageBoxSprite_vert.glsl b/src/shaders/vulkan/CCMessageBoxSprite_vert.glsl deleted file mode 100644 index ddd48ccfa..000000000 --- a/src/shaders/vulkan/CCMessageBoxSprite_vert.glsl +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 UV; -layout(location = 2) in vec4 Tint; -layout(location = 3) in vec2 MaskUV; - -layout(location = 0) out vec2 uv; -layout(location = 1) out vec4 tint; -layout(location = 2) out vec2 maskUV; - -void main() { - gl_Position = vec4(Position.x, Position.y, 0.0, 1.0); - uv = UV; - tint = Tint; - maskUV = MaskUV; -} diff --git a/src/shaders/vulkan/CCMessageBoxSprite_vert.spv b/src/shaders/vulkan/CCMessageBoxSprite_vert.spv deleted file mode 100644 index a6a23d34f5144d549093bb64be3754aa4409b142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1364 zcmZ9KTW`}q5QVo%+$*&7&ZQJLy&|NFhqkJO03kr;A*huKeYK**s#bN~D0V8~iQmSr z;svSaTYDpmtxjjo%-PwQahi?oDPtzgoOx(on({1~h9X9>NoS+ZMdvUt`iDoyuTjjK zrW2xB&^=B|xaryqpU9H%LI{Pnup{gV`$AKH4cR{`&@!_o>cr96S=9L)_XdMFFMg&; zoZ2jj`*xW03VWBJo380>)=NkIx*(9E-b0|?=k&%^8lNY_%Vbz2KSUKR1>1FPeIeJ#^V`>MVY+iJ;UNX+H5ptt69p?hgS#HOeK!5CH{GfdD z>}YgX`l0;qm-sEWvqC*6>O`>jQNOReT=z?F@ulc z6Jw{5GWh5sMVMn#;J}%o&cllH2Kn}XoLSKOddyPi%mSx}WvS3@iNW#Lm_-1^Ucj^L;o?7f>O9%yW e>;_Jby1N4Nl4CD$fA2s(vyx*6@PFFOsc;YHFk&76 diff --git a/src/shaders/vulkan/CHLCCMenuBackground_frag.glsl b/src/shaders/vulkan/CHLCCMenuBackground_frag.glsl deleted file mode 100644 index aa090f0f0..000000000 --- a/src/shaders/vulkan/CHLCCMenuBackground_frag.glsl +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 2) in vec2 maskUV; - -layout(location = 0) out vec4 outColor; - -layout(binding = 0) uniform sampler2D ColorMap[2]; - -layout(push_constant) uniform constants -{ - vec4 Alpha; -} PushConstants; - -float remapMiddle(float value, float newMiddle) { - if (value < 0.5) { - return mix(0.0, newMiddle, 2.0 * value); - } else { - return mix(newMiddle, 1.0, 2.0 * value - 1.0); - } -} - -void main() { - vec4 color = texture(ColorMap[0], uv); - vec4 mask = texture(ColorMap[1], maskUV); - outColor = vec4( - remapMiddle(color.r, mask.r), - remapMiddle(color.g, mask.g), - remapMiddle(color.b, mask.b), - mask.a * PushConstants.Alpha.r - ); -} \ No newline at end of file diff --git a/src/shaders/vulkan/CHLCCMenuBackground_frag.spv b/src/shaders/vulkan/CHLCCMenuBackground_frag.spv deleted file mode 100644 index 0bc0033db440df284a0a5bf31cc966e09ac75fab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2392 zcmZ9NYj0ac5QaC69nxFUlBNY3ibE-FDFh0=652SV#eq5`5K6ea2ivF?j$_4k5Z{mx z|EZt*r$9(tp68si;^0-rGw;moJG(o(CzFTHKNG@4I2w+J??X0DhC_G)zNu8#>f80D z!LYS-?fP40%!J7_(VW>Z9ZG0rH|g{YTtk+T732iD#wda{33CWfnOF)(LapAYZEn`; z_Z!WAzcCp8+-*0yonE`q>g>0h!_Gn5yy-$-r`PO`TE&Di8O7RVDjlW9etS3RZ**F% zZu`;?SC{zj%&B7Zll^2D?Yi!b;q@_GAH!Q?c>9029KHfK z_j-e2(i;x2r>LUOvD)oFPS9n%-=McfgU4%y+#2g~&o3j6h!-=MVtah9fbF-~{+jQe zV|=|(`#gR}jWcvT=Fjn~UQBOD<~xl&g|CuIDZM}5A$^PRP3N{g8%^-}GQ!vhA zME_js{twS*xEkXNDgI^U3_Pw;F7H)^-&fGq(EmI)=vB1w38Xk8KFiuK5-@L``IpcY z#9=-0WyC!%fL}wKug`i{&<_2}Ikq1T`QAWR5bMb&UP2tse={>vPWSUR*!5b^_&aFl z>X%<^KZ|^~avbCK*SPcVqWuDR9>&G?TVLGYDz+oy53wV^``NEarZo8iw+ynPypB(c2fv1diu6^?@+q;N;s}ZZKWBA?}ULV80!{U73VG(cV zc$HPy2S1qh&i>qCO&8Hu5&dF&a2@gdcbMZj+(69Hf0tdk2Yr$AHnyDhD004wtv_Mwa-+a$ed>baYYKY(E zDq<}1e1vUX???X^>t04;-A}Rg z%VS@~G5<4c>lX7Lg7uqk-^H;mpZ>J2JjNo=7ufRbAhGV3*!ovFDew1phSQJM|>LF+Hrqpu;&r|$5^53 zeGZvGJexU04)gwo+n6=16*5>&j`&JnL4_ L)^*?ipga9ExW)aj%72R4raE2I5@W=FA$`GTA#n9)Tj05KT zHE~p9YLM^M*x#pD^wikUtML0mVB&2>3-Xa{NB8x^bC_PXggf$)jB`}u$BL=9E4(Dn zeYibE^zPpvhegsomG^VLt1;gLjyfw&SG`Le@T!bMUu*Kzp=aLf%F_cp?}6DBobPi( zF$evoJUQMVkAE)Xc>Kbl`;X{%71JBDfc*}AJuu$_jjtamrUsaNPu9%$>-?F1Gt9w` zIcWZh3FSZOKfP|rn1>nOOG&@mGI+1qQH+M&d(AV&@E7Ww-e1bN2hY6B$bIH}CF2{g i=MU-vjGnicb6*z8$T2I}=MEGz4>{%p|I_quW&Z&^!dhYg diff --git a/src/shaders/vulkan/MaskedSpriteNoAlpha_frag.glsl b/src/shaders/vulkan/MaskedSpriteNoAlpha_frag.glsl deleted file mode 100644 index 8c624cf63..000000000 --- a/src/shaders/vulkan/MaskedSpriteNoAlpha_frag.glsl +++ /dev/null @@ -1,35 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec4 tint; -layout(location = 2) in vec2 maskUV; - -layout(location = 0) out vec4 color; - -layout(binding = 0) uniform sampler2D ColorMap[2]; - -layout(push_constant) uniform constants -{ - vec2 Alpha; - bool IsInverted; -} PushConstants; - -float rgbToLightness(vec3 rgb) { - float maxVal = max(max(rgb.r, rgb.g), rgb.b); - float minVal = min(min(rgb.r, rgb.g), rgb.b); - - return (maxVal + minVal) / 2.0; -} - -void main() { - color = texture(ColorMap[0], uv); - vec4 alp = texture(ColorMap[1], maskUV); - float maskAlpha = rgbToLightness(alp.rgb); - if (PushConstants.IsInverted) maskAlpha = 1.0f - maskAlpha; - maskAlpha *= PushConstants.Alpha.x; - maskAlpha -= PushConstants.Alpha.y; - maskAlpha = clamp(maskAlpha,0.0,1.0); - color *= tint; - color.a *= maskAlpha; -} \ No newline at end of file diff --git a/src/shaders/vulkan/MaskedSpriteNoAlpha_frag.spv b/src/shaders/vulkan/MaskedSpriteNoAlpha_frag.spv deleted file mode 100644 index f6376871a4e8994628c445dad36425697fdd8a9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2708 zcmZ9NX;WNP5QdLo23Zp#S&WGYK~1WnxMUYYAecO8}qrLooC+Ci83c^|zjzE$7G zgc<0cb$2hb7vSpc?S3uKzgh1-xpzOyy`JNx_Vz}-pIb^d(A)K$`eq-O)5qw>R;Sym zcY0myK`P0)B5x2@&ih~Ku5|XAJG~|sU52m1-QMkPEEj5cPUp~Tb$X~&0eh|~0ZZ(; zPWI9Nc&31zXEENhiJj%mLXWdxS8(&k*D5(msMUh@M7{ z67TyF>z@W&Q%;!y52N+V>mNr)&SCI@KF=@KnH*1K@EM*2+fVq9V%v+@+NTiKqWzq~ zkn`=i-&<&Vlb_GA_bhje?&i?OTfevhA1Cr19LAj>-;Ygf57vJV?UJ{?*txkp-&yoD zVm>cpU=#^W+`0)+mGkde;IAAy!FM-T~7ZMwD;-xqW)EE{SkjH$5X^RYiniq zUP_-}J0p4H#lBZL>)*<4;}6l*ZFJoGUF?*8x@z15teAE9>wSM#r-5xxF$b}4E#tCx z&;mOb>wTZw-o*vpviIRkUB>(cQ%2jfcd&qX4`Sb#-*sT$-i;hDk>#CVK%A4axI&II zy@<$*v-{5O`T;ri{b3$6k6xe)-;rF@T*S7f_a8NvuorV|&1J-SM9q(|jghye=a4hs zJu7`arB%Kl&vP^9%i?tKq&zhClR_;Z_lFY?ig+~4FyzIusl-_jR|y*VHE zj=EoB>kIr9w)^~=@AEaboN=*_T-5yrJL*niN1bo6^#%S8yV!pXEN5KQm5ca?*v5}B zC(r)~aW>BIAyP*?f8^>nSAP@nTL}CZ+qdPJ^sggw#+k2AF81EQc5mnEck=`>#_uU& z+BqNhv@^Q#|z;os}Hi(}aGk^c&I z=eK`-QR@Wu^ZmXGCm%6Wc}%h2*Wl!1ziDjudjm0Ff8@_#Ki}_3IQht*#g6=GZ2k7@ l{pyQzzK-n~0=u6vKj(9N6WbX1-*V17ls|?1%RI%-{y(PDyU+jt diff --git a/src/shaders/vulkan/MaskedSpriteNoAlpha_vert.glsl b/src/shaders/vulkan/MaskedSpriteNoAlpha_vert.glsl deleted file mode 100644 index ddd48ccfa..000000000 --- a/src/shaders/vulkan/MaskedSpriteNoAlpha_vert.glsl +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 UV; -layout(location = 2) in vec4 Tint; -layout(location = 3) in vec2 MaskUV; - -layout(location = 0) out vec2 uv; -layout(location = 1) out vec4 tint; -layout(location = 2) out vec2 maskUV; - -void main() { - gl_Position = vec4(Position.x, Position.y, 0.0, 1.0); - uv = UV; - tint = Tint; - maskUV = MaskUV; -} diff --git a/src/shaders/vulkan/MaskedSpriteNoAlpha_vert.spv b/src/shaders/vulkan/MaskedSpriteNoAlpha_vert.spv deleted file mode 100644 index a6a23d34f5144d549093bb64be3754aa4409b142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1364 zcmZ9KTW`}q5QVo%+$*&7&ZQJLy&|NFhqkJO03kr;A*huKeYK**s#bN~D0V8~iQmSr z;svSaTYDpmtxjjo%-PwQahi?oDPtzgoOx(on({1~h9X9>NoS+ZMdvUt`iDoyuTjjK zrW2xB&^=B|xaryqpU9H%LI{Pnup{gV`$AKH4cR{`&@!_o>cr96S=9L)_XdMFFMg&; zoZ2jj`*xW03VWBJo380>)=NkIx*(9E-b0|?=k&%^8lNY_%Vbz2KSUKR1>1FPeIeJ#^V`>MVY+iJ;UNX+H5ptt69p?hgS#HOeK!5CH{GfdD z>}YgX`l0;qm-sEWvqC*6>O`>jQNOReT=z?F@ulc z6Jw{5GWh5sMVMn#;J}%o&cllH2Kn}XoLSKOddyPi%mSx}WvS3@iNW#Lm_-1^Ucj^L;o?7f>O9%yW e>;_Jby1N4Nl4CD$fA2s(vyx*6@PFFOsc;YHFk&76 diff --git a/src/shaders/vulkan/MaskedSprite_frag.glsl b/src/shaders/vulkan/MaskedSprite_frag.glsl deleted file mode 100644 index cf424e6c9..000000000 --- a/src/shaders/vulkan/MaskedSprite_frag.glsl +++ /dev/null @@ -1,33 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec4 tint; -layout(location = 2) in vec2 maskUV; - -layout(location = 0) out vec4 color; - -layout(binding = 0) uniform sampler2D ColorMap[2]; - -layout(push_constant) uniform constants -{ - bool IsInverted; - bool IsSameTexture; - vec2 Alpha; -} PushConstants; - -void main() { - color = texture(ColorMap[0], uv); - vec4 alp = texture(ColorMap[1], maskUV); - if (PushConstants.IsInverted) alp.a = 1.0f - alp.a; - alp.a *= PushConstants.Alpha.x; - alp.a -= PushConstants.Alpha.y; - alp.a = clamp(alp.a,0.0,1.0); - if (PushConstants.IsSameTexture) { - color.a = alp.a; - color.a *= tint.a; - } else { - color *= tint; - color.a *= alp.a; - } -} \ No newline at end of file diff --git a/src/shaders/vulkan/MaskedSprite_frag.spv b/src/shaders/vulkan/MaskedSprite_frag.spv deleted file mode 100644 index 65f815ccd43d756065be0aeda7534a067efe5920..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 zcmZ9Md2>@`6o+3(TlP&h5yTXvvS>jCL=dnR2$f)wmd%9_lgyAYO*74HNB?t%@zeM% z{8BD6&iFj{-lKPTGpFaA-+T7+-qtps+>+9!v?J|Gy;PiiX){Oyo632kxzwB;XWiM0 zmo8|rJJoVSZT6&XX#y^-wEIIZwn1+~b!Z9Ni@ox;o2L&dO|;nf#xV}DWWC9vrAGO{_16aLqc?Iq&hLG~E$0o>Tyt3QNm8*f3~ z_a)~2aw%(nnOT_EcjPh7pCFTPXW(4@rj0cR>Yffj?$-TX$HsSX5E55+o<|_}^8_D# z--5Iezd;uJ6N{L>ePg<_i1`k(c*LAWu0s*?1hO{b#E2G4_;1)0 z`ztW__XjaPfP4O?k8|+%Au(s7Y;5=UA!I)HYJJY~BS`!eHtHWkz60^_yNDcq)~v4G zU&N0*@;M^-4nBeG!S`W}k?RVwcMC`zEq?5$AK{h!Zw*VB#^4FObFb4ZnHh@H4-9VOPxgR^>k8-Ubuj$$vfP+<-Pg z?#sJ7kaLe5caf_()b;Ux2EG8d?(70`zz$g z9rZ7QiEHDx`!(eE;9GJA>e_g}41Waq{Z`-F;}VY;PtYSqeiqzeE5 diff --git a/src/shaders/vulkan/MaskedSprite_vert.glsl b/src/shaders/vulkan/MaskedSprite_vert.glsl deleted file mode 100644 index ddd48ccfa..000000000 --- a/src/shaders/vulkan/MaskedSprite_vert.glsl +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 UV; -layout(location = 2) in vec4 Tint; -layout(location = 3) in vec2 MaskUV; - -layout(location = 0) out vec2 uv; -layout(location = 1) out vec4 tint; -layout(location = 2) out vec2 maskUV; - -void main() { - gl_Position = vec4(Position.x, Position.y, 0.0, 1.0); - uv = UV; - tint = Tint; - maskUV = MaskUV; -} diff --git a/src/shaders/vulkan/MaskedSprite_vert.spv b/src/shaders/vulkan/MaskedSprite_vert.spv deleted file mode 100644 index a6a23d34f5144d549093bb64be3754aa4409b142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1364 zcmZ9KTW`}q5QVo%+$*&7&ZQJLy&|NFhqkJO03kr;A*huKeYK**s#bN~D0V8~iQmSr z;svSaTYDpmtxjjo%-PwQahi?oDPtzgoOx(on({1~h9X9>NoS+ZMdvUt`iDoyuTjjK zrW2xB&^=B|xaryqpU9H%LI{Pnup{gV`$AKH4cR{`&@!_o>cr96S=9L)_XdMFFMg&; zoZ2jj`*xW03VWBJo380>)=NkIx*(9E-b0|?=k&%^8lNY_%Vbz2KSUKR1>1FPeIeJ#^V`>MVY+iJ;UNX+H5ptt69p?hgS#HOeK!5CH{GfdD z>}YgX`l0;qm-sEWvqC*6>O`>jQNOReT=z?F@ulc z6Jw{5GWh5sMVMn#;J}%o&cllH2Kn}XoLSKOddyPi%mSx}WvS3@iNW#Lm_-1^Ucj^L;o?7f>O9%yW e>;_Jby1N4Nl4CD$fA2s(vyx*6@PFFOsc;YHFk&76 diff --git a/src/shaders/vulkan/NV12Frame_frag.glsl b/src/shaders/vulkan/NV12Frame_frag.glsl deleted file mode 100644 index 66a12992a..000000000 --- a/src/shaders/vulkan/NV12Frame_frag.glsl +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec4 tint; - -layout(location = 0) out vec4 color; - -layout(binding = 0) uniform sampler2D NV12Frame[2]; - -layout(push_constant) uniform constants -{ - bool IsAlpha; -} PushConstants; - -const mat4 yuv_to_rgb_rec601 = mat4( - 1.16438, 0.00000, 1.59603, -0.87079, - 1.16438, -0.39176, -0.81297, 0.52959, - 1.16438, 2.01723, 0.00000, -1.08139, - 0, 0, 0, 1 -); - -vec4 getRGBA(vec2 texUv) { - vec4 yuvcolor = vec4(1.0); - yuvcolor.r = texture(NV12Frame[0], texUv).r; - yuvcolor.gb = texture(NV12Frame[1], texUv).rg; - return yuvcolor * yuv_to_rgb_rec601; -} - -void main() { - if (PushConstants.IsAlpha) { - color = getRGBA(vec2(uv.x, uv.y / 2.0)); - color.a = getRGBA(vec2(uv.x, uv.y / 2.0 + 0.5)).r; - } else { - color = getRGBA(uv); - } - color *= tint; -} \ No newline at end of file diff --git a/src/shaders/vulkan/NV12Frame_frag.spv b/src/shaders/vulkan/NV12Frame_frag.spv deleted file mode 100644 index 6d162a11c7a4fb6bf3b44f2d8f905555f212220b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2572 zcmZ9NT~pOn6o)s^K?6exQ52&CSXmk+DQYGJmZ*`U=1Xtp5qUEN@*J4DtBYouu9~qv zMfY9mjMGII^-a3(WyYrGIqY@jKkS*sTEE{~d#$zC-v2{O^Wc`0no@h(n!ZRIt1~sj zB)HbPo}9WeHB_zL89H+Gbt5`bOFht-?d*FBt=y|DF6($7xhO_<5UY`T&-1>YgO!4;^bWCs^d$m3l*5w^bUA>t-5f!5Nm&)BZ`#h-7~Gx zguWZts}+i&#kV)%#ZB0_+TwBzl_rU|-+lor@W2KHx77P=2A?hTJlODW^ww9v_EyB! z6MIKpOx;}l^&3cadlz;qTp8I-Ki-enxH5PvT29gbG+MuR*3aKIw48Cqcc6`xI|w#* z2a?j)V~6m_cOr5{*@NdYl?MA!g zPiE}=UFO?^E+f`6pLj3ga)0lJST; zBlB%PjRhVCy8^#~{mc2^8~!8UoW{r6*uVbx+rz-ez<=~jKMH&t zJn~>m?~HRkZy2CmRO%jK|sKOwJ(A$v1t99QHSf$p1`?b2^u~GWsv7zK3@GOT51G$O2+7 z+U9mHmk?)FM$GLQFC+31a|PQNzk!JP09*b$^0?<3BIjJE;XL1U#9aDD>B)1;oxtzx zK18-5^7_3~xv2XQ_U7I`hLew&PjXDLw@=~Zqqm#ba`yI3?)Mh9y!RgcRn7#Mn9e5Yc(mCBlJg2eVy*O%qj%`i( zn2}sDmpRSlO#KJ$TMWE{Z7<*EnXh8Y85jBFp745)BfekrSku*p9HTGaX**)?&!BzF z9q8?dXE2v`C*mA>(fg1dB;IWo_H&t!v->~Jyw`Kx=W~pF%(x$0-ev9q^dMrrGGcA9 zaZ&pPY-{gFtYz&N5&5Y75_YlnfgB@$kyClDml1iz)r3S32eIwJw->!0!gi0#zKoHJ oJ+ETBryGeqL)h*yw|k6{i#vP`+dV(z8I57fjUxYXA7bzBfA+7ZF9Y7Ee5fDV&b-9rc4?;|g8iL7kfCPhZH5;9niR(hxff!HzHh+~D z6TYu^dflGXRKHi%RrPu%YjmbVxEJQaOxO;iwG9FZ>v)mizgFfYaIMeML&UVSKsRd4X67{^p$?55uz$8zR# zepk+;j&Z}tWl`77t??}CJHHrdQD?;rIAYDH`O^ee|4DE7-TW?R)#`jlWV?4IpE$M2 z=@aJ}Ip1kd6nm@6>po|3)3&vCA5NVRHOiSZ7$q)bkNmEvq$$8*^(lXOB}l x+xrP-t}*qi`G6YEyMcM<-s?NMip@_w{ZG_rEd6)Jtos5}k1=(N|DoQ~_V!B|@{PI0%%`}BNMTsTUze30gu_O29gth?-b zkiDRDZCm(plD%A&wBF3GTd2*z`0fA0ePI&goLuJm+mhG8?>A22Pgd(njNUKOvtqxc zy(_M#+SWX>1(QQh|Lf{_!Jp4CnZWHTon>|O`WgPLIo^|UMJMQ(w>ne7F%QfeS@^fq zna4fRx7C>ij~>jM;WmXg)O#vcS6*a2<*K%&J$HrUTQIr9ohmClcqfbZe2J;4Ux?*? eO%-FyHs%D>=W z@>h9d;`{9GY4(um%)B#aKHfc)OO1JB=FE~=HqT6U)=Wu=5mrsL+d6F>MDg(8#mnbp zteA3|NY1Lcmf98lUiSSEXIXMv@=&rbDeJE!{YMunX3@BrG?tyIi3ej!kSF`LRC^ zh0dq>?2zJq7@zt-)tNh4jF}ZX4E)KFAI1G};LTz%Kr9J@S)j^he|A z<;P?+@}}+cZ`w~aDrtK} z^jp_2x-N{pus3B@rE8Kc&BL7d?7N}g1?ifE)69MTBj~pye^Huzuw7a3V`~sYYRbDV zZMl4t`@AJE`mCgRSzY?zuSz)E^5KrU%(bgqa0o{2o6_t8Ms0j}1tWedx5;P6Eoo+^ zH}P%hISDxT@!=heS;)OBG3M8M^6Rp=%RJO;NRwmxJ&;WtoO<|tH!$u$lBTwe?&6HYkP|0{&|_(8wyy&-`MxO}TjIM|ech%M2Z{0U!4z+$Wzny!}>PVl@f9$zi^_^qz!wz08?*L|tW@ekF zxuumUE#}&4tCd-{n6#LcrIog7R$7`{YW;rap7(N`=kYwxpZ9(L-@AU_cg`Ie8}@8X zl1a(bWQSz>q$GWIOd4PkxRzA*^seh&Sg8&!JmA3nb(oekrhfWNPbMc#NU^anTykMA za41*_o&huPcb!6Ljbu-fTM2GTrX)SR{XJ{f_Vga!KQKDlU#XrpQtTfYE*1L+hsTNo z)!|J={n~PV!=-_d@xi=9GamW+&GbE$8kItIe5_C{&fhe2fc-R6dkS((sy8Pyk=5ds z<>is`7%J<{$t+|_tSOAvxW;sz@lCb$`H&k6l~ei(V}*@b%pzoEv^Wrn>}N4tsXVr^ zFj9-N{^s)7$ly^m(ppR481tBN@9_E!RsC9%F1Y0zNIp<4j&-hBH&86G0|^t=*3^$1 zE^h7{E1&HCl-cnXBD>%{k7I^QWRh!3IrsW_>!vmO%9Y`WsjYjG>H6WP6}PV%-;&0= zuPX{;r>rRtrhT}F-Ecnk>lvqWtsE5j8nE=LLMSqrj&rxe%Yx`Z>2H7r#IZH2!VL*5|LUE^&mT*+sF}Ygr#C zmnzjlsaiqz+~j;#S5_1%8_d&^T#wy1UfHlb=PUmO_}txCQzXC~@;=?=Qn8k|HRZey zp4-UU(ZaxR^)!9F7y5fIRuwAiHWUWSn{yZ5{l7^^9(%qSS=sKCa<{{ICfo0OOL8aN zNrg($`D;dQq%$Jz zeR9V2kjr;@o(?==&qepnYx|v=4crTD-%)K-titX>`ZR-8{M)6$vu8~_kMr9$1B9PB z^y|uT){*PWarPp2Vvh5jlXK7>y6r+5YmeQ?dB7)ZXY$eZeRKvNdx`sHJ|FYRMZV9Y zw}39-%yE}u=CC8)oWbR1mW!FWVrgwT>loVvXYJtZ)q9qoMcY}TH}AssS(?(j098Ma zIRAWa!9{P@l#86+k9wZx z1L-4wXlDCf_?Yh{$PQpV^J&MP8$Soz$DGdZ-r28v4-E6W|Hi)(X}o;IccMrASD{HWO|sUCh;p?ePVz-&&|Z?7@txDM&}LeBf9eSOBcenY0~ zZx71Pfezri?zh{!EH^v*F30ygYJ8D3`}DhO4Q;=(atpYj`y+1y-qV1!@50u{-nH+^ zZ0}&~-Tmm>?&#%AYk3~T_S+T+zsKN`&Oz@0v%qX{7(4Ip&0Nrt+4GPu z1$%+xiD^Z?4Co`jgj4cNht~8yxo$pvUkwfg?b*9` z7`pz41J{i4&dJ;7a^woo4Wdu;=r136d(c;cvxsqh70^dMYOO|(TCQ8m`z#-|deNVRX9$t^`9)$e{bo(^keS9O(M?PkI6MD?% zx_N!C<)gO~(XG`-9`9=boS4DA_FXy&`2PEMRNUDCbbWoytB+j76w!?t1Q9cYZj3z{ zqmNw7v;jT8&%@Zx82fxOx<2yWANTeYFdevN&h;4=^NnCTU)USb^@+16q3a_bdr(G~ z7ctMN=*}|=VxBQ{eSNI0k6gr5(T%Bqh#5yWCiXxdIs0oxo(YU;=bhDl2hi7V;_2WF zppX5#{w|=;*}xwB4$DQpccYun{nGzDAa^c^93Ra13y|ix5Gl7fi@6AWDv)>m9Hg9c zUW)t>=mwVn>+XuY49H)HkAJUxIO7%~qqmQs+i%z(MK^aJonC?b7%(o6YdCf1xDvQ- z4&&_WV&s(|@_ig#ZY>e>ke>i@!lwa*?iYqoyAwt&F9(^^z(J3&(qX)?Q7sx;NK+b)|-R;2ABono4X78H#6S)&iyU07l_}` zThR59kKdthqu-JNk?vCi(!IGE>H1UDwl90I7xR1W-vKj0+OUB9j z#Gag&-Jie0>0>VYxDP28d+-3dT-bj@caP$4rH9ZT1oE-Ze@8dYwTSx%x^ZV_b^nPj zr*F(J7ygf+FV5NjLO%h-@9w|R^^y0zaz7pg&Nm;pJ`Kd$f6!gq9q9KMu^o`l%!v9%x{o|~kL-)+`cj|xG^7?r9Z2l%h z+<$wWZHQRkX7t^v;9x>jThobmd*Zhq%^CR=-!;)ekL z@2LM&;4>KB5wMFR;0G%?Xo>|xnl$c1G$?rw}ADvF8)3szJ_ z{VIMc|M7Wz-@A9<>d7;EW`0x7lyi2|wRo^ENfss7Cd-mPlg?V6ECxxydh>mBY-(&{ zt39)E^OlFTxIXF14Yj!e$<+;=sAP5dl~6x)3OWmY27L$p0Q~}8g1Y!y%>EZax|5~J z=-Bk=#Kh>>uIcLB+;ppbvX)NQvU)l_lQq+7J9{hDZb`{5t5<9DGi8GwEXsNGBz;6q zlGgFGmbNRkea%X}b)?Ze0oFrpWaYc$6zb6`Exd83A`9{%i&arf3|vMSNV z?3LKTG&?%m?qG+(+W*P7FR6l+^EDNqJZE*TJU@2NrDgfDR%@cv{%CD_GHo76o9#4@-&^3Qa$THY zKee}?`ZTh7dn!AXryDx^iEg--&5dNOcBNiTiPrJ+_Nkk%)voBQ*L&tN*U#BYy_%|~ z^(*n!xejFM!ep~?%==~G&R(5)?IR~`oUfSq9JEhk&gg3Kp*N>ozw2arRjYq*?(e-E zsWgu}A6QQ6O3ur$?6>bD@9p#XkU+Zg_fm+ty>Dm!t&Xp6X#atZ?`8OEqi&bDJ)Jtl zTzgw16|Ob@y~!WQlk=_F;ganr=PU#7g@&L#$li5V544BRkOy=0zZhR0`TY(%dzafS zxoT(c#Ja&osoQvBp6%OM54l2K2j9_m^xJftAxpmMcw*pXMJ(cqrQ*_(YuTrSkxDo=V~`pvNNvOWC`Alz7pBq4?wOBg?t_S0CXF&Z%bRTe)99~$9wDecJmwB z$xq#r_$d1>%+)iNvkyRvAkR>~338e93U;x`@n(2!#f_)z+X;WqT?M(UX*IjL&NS8s2Or)IN%Kl!7_2cn5yFJj?v!u8mU%*?xHu@_2j>L?8 zf!#Rzsy9d9kyzB|JF-T5c#+-w!vAM@ZN;@$_MM3t|5tW>L$B<+6LWsPugLXxc;ASa zv6TOS#2(}Rd#3l)W&FQE{C?6_o25|Hp?tU`JKGZ_+1dL4i}pK+;yqpidDp$)+llF& zUJHrupla{-t&s1_H>6HGdw(0G&RE{*0myqEvFzD8XaM>e8-3P8`iVylcfy;)AQU;= z1uq^s+zlT&sEZu#fmatf+zW3G5z8FzgTy0;`{DHye}TO0#|FsUT!B3RudVBY!tOzM zZPkU{MtFS}m9U54^%V=>hvBtV7ru|c>$|vwJqoX{Som&&*H&HlZid&_dlA?cczwmf z_c3^F)lE{Zb9fxG7IQMTHan=%JMjeMJhnnHk8K4W^LP?D=Aka;@f5r|V|gdGL(U^& zIgh6cJm&EXvVP)G#}K?Zx&qq)udOR;+X+7esSCSdczw(B7(v#zJda(-+NulR-SGO_ z`@lxw^%aYA_rPnbF6{Qg>sy}3v&j0E=kXk}w(4RYWAN5uPR7; z9`l%lk9nwzdAtCxF6Qwfyz_`y&SMG^k9q8a*H1iZ+YfJ!uD}k!YwL=>9E8_aUD&+@ zuWxxCFC*()p2sW5+NulRSK;+7&*L>@earKB9a&p-;rj->zU6sLBkNn9$01~G)x|t2 z@YZ5Z#y$i+jn`6kb@uZX_9IXV-2_F?j}~~yv&i~=i;r(FgR~Jh=HUVh`#Q2%)X{(! zb4?K882cO~F1hSuxkqmz>mwdMO?Yw1^?#ohm_Eh{pEkU>&qL;7Y;CRQ z1iN_D^ESNoD4Y8`&?(6JynpW&7~2)>y#n*RuzSD2%+ERXv7dqT*IxZ;=mK%oeE@m( z8OXdA*u~64{YQ{k)cSFOiMyg!ea|ARkGX#de;z8&{VQbgi2pUb@gtva;I$Dq&IR^w zq0b=Wc#g7m#<0KNL-sRz_apodkTLD$Pmng^`hQno+FykK4Z2k5ektUCsBA0rFL(%+ AhyVZp diff --git a/src/shaders/vulkan/Renderable3D_Eye_frag.glsl b/src/shaders/vulkan/Renderable3D_Eye_frag.glsl deleted file mode 100644 index 4d872ece1..000000000 --- a/src/shaders/vulkan/Renderable3D_Eye_frag.glsl +++ /dev/null @@ -1,59 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; - -layout(location = 0) out vec4 color; - -// IrisColorMap[0] - IrisColorMap, IrisColorMap[1] - WhiteColorMap, IrisColorMap[2] - HighlightColorMap, IrisColorMap[3] - IrisSpecularColorMap -layout(binding = 3) uniform sampler2D IrisColorMap[4]; - -layout(binding = 0) uniform Character3DScene { - mat4 ViewProjection; - vec4 Tint; - vec3 WorldLightPosition; - vec3 WorldEyePosition; - bool DarkMode; -}; - -layout(binding = 1) uniform Character3DModel { mat4 Model; }; - -layout(binding = 2) uniform Character3DMesh { - mat4 Bones[32]; - float ModelOpacity; - bool HasShadowColorMap; -}; - -layout(push_constant) uniform constants -{ - bool IsDash; -} PushConstants; - -const float FALLOFF_POWER = 0.8; -const float HIGHLIGHT_TINT_INTENSITY = 0.6; - -void main() { - vec4 eyeWhiteColor = texture(IrisColorMap[1], uv); - vec4 irisColor = texture(IrisColorMap[0], uv); - vec4 highlightColor = texture(IrisColorMap[2], uv); - - vec3 eyeColor = mix(eyeWhiteColor.rgb, irisColor.rgb, irisColor.a); - - if (!PushConstants.IsDash) { - // "Specular" - vec4 irisSpecularColor = texture(IrisColorMap[3], uv); - eyeColor += irisSpecularColor.rgb * 0.1; - } - - // Tint - vec3 baseTintColor = eyeColor * Tint.rgb; - eyeColor = mix(eyeColor, baseTintColor, Tint.a); - - // Highlight - vec3 highlightTintColor = highlightColor.rgb * Tint.rgb; - highlightColor.rgb = mix(highlightColor.rgb, highlightTintColor, - HIGHLIGHT_TINT_INTENSITY * Tint.a); - eyeColor = mix(eyeColor, highlightColor.rgb, highlightColor.a); - - color = vec4(eyeColor, ModelOpacity); -} \ No newline at end of file diff --git a/src/shaders/vulkan/Renderable3D_Eye_frag.spv b/src/shaders/vulkan/Renderable3D_Eye_frag.spv deleted file mode 100644 index ece318102d766e30289b036c5820e79d6a0760a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4188 zcmZ9NYg1cQ6owB3g0}Q#uh@zK)K;rl?Zqlmpnw4ll1eRJ38%@iIc=K6B!GCS1*v!I zXZ;1v_%HlSe~*_LXMCTNz3QIsnU%fPyY6f6eUj=N>Is65U}vx^_&I2=eL<&?Kv+82 zv$=)baI;k!K6CaI7Q2H~Vu;P2peN|k4&4mnDvBebTcW+P16KlZDMbx}KjhRE>-9pjwO)w|mAD!eN^v79w&K+YyN5ixxLT~NlzfA3S@?OoRqw;f5v@my z<+v41)+)7zWbnP(XB%-d!RErcMB%BV)|FNG?%=4f*lZGgIvCJij<1y~qLvGY?bE`Q z$5JHzXM`1N)n+TKwwmJ8Lcv(G&8e_iZr5^7a(<;*p7d)@}%(OSMyyUtu|Iw9)9kMkoQ zHfhZoj5AuSH7cbX4d-jk*nHZ0PCn63uSfrD@lPlIoX1qyxG`5NC3P_4OTt*xyQKa8 zJiTT(OYTh3JF`v6UT<@e21xDTtc$g3)Sh!sg3%9oEA#cR7`N83p)c&|YbIVe3hFaA3gLXeB;n0y69V^M99p9f4BnYyqpF1}AfXw}2X6Shr{Z2n4Z@U{q z4$I0CEU8uYoCm90guTgT?_<0%@*Bo1up9R<;)3NpEak9e59186qj74odqEGJrQahm zJ+jbqhSnqUhUBzpTr?wjQ#;FgGMRiV>Nm{q3Cw!Zk>0oK6pn9~FlxmPjNF{-ponEM zwW6mMJ5Q^{WWN@}tQK;BSq{$M&w)%1YTYj@>;~kM(hh$}9P`MC4yy*@A~W-he$_^T zf%oZawnIC5;`z(uql&jv3hWNbzgK%k#5(EZUE+yGwXAzTr4r!-edPRR&JHFt=N9G;)@s3GmS$yV+Kk<%hCm!=7-U;o@ z2Hg4^7H|6JogSZlp}eQ|OuB-z;`x67qZVYo#bCsK$?@19PzA4Ow;UtlSytnOcyc0> zYesZ$dwcYVd>Bmb)ze*I)X^ ztk$~Z4yPv%-$;x1g?Q>F9{G@Yv(^jtw?!Ed_hmynwci%?ySE8Oe(T{Y@xCVcm05f_rV(&RSn$xgCcNb?s=bxJH99%ay=@-2K<7$pk^?O z`IvZO@(wH}-%xOi`M7vLW=1kL;KZcwjL2dRi6`cu$YMSr9^7I+Dc+Cylw@qciOKB1 zu&0k_MASa7$sgB#(qZ7N4iV>N_Ror^F0+45JQ&0>durz0o)Td{EFuPX>;(~cUJ^N9 zbQn0)>uNbIo_P3D7rC&d56&Dtd3fXJMZ9~Pcdz)D9sav)c=xY5Y()ESss(J+;eRUT zn0VGd(t%$PfpI_K?Hn$O=Nu+P^u&Fc6oDgiU#3LL3Q9Lwx$waT%zRqn@o9?8 zXGJ_dog#d&0kiq6insg5nXie6Ve|dOVc@I|5wR@ix_IpUS$--R+~)R~crYWI+vmcF zhc9)I3tQ@>CiGV4m*T<5%R9Iu+7j7Yyy#(+0n_# z(eYEW<)x+BX6r^Zovl`C>Fivkk(OJP>#26@3U-xRxw<@8H0Z*j_svpP?fAGhz)vg}yv0^CZyQJtHrH!H15-2wTwvnfCz z-N`p#SE{p9X=5gBv{FUTHZHF&qSzY^>`jJOYOU$Y&FtyW*&B4j)ymRHrP(Ug$|=#> zer}Muu`CPCU zHkhV?5k zHGBU6UAbPfBTT)WvzX^}bEL#NV%42IM4no1&JP!CM~Sx)yc-&X#*p1nPZu=C&yWW) z^l^-jJ=@E$vrn1bx<_{QNvsoWl)8*3=G*S{ZpagIKYUx?k?nct;`e}kHO_M?IQqH! zl08+ohub6new)qs$(*;&a?VGcA)BkmngWYDjVBiQJGf&0%I0q$%**e>ygbIsJ_7g+ z8S)6zUd%h}d_%0GfXRzRoyOD7dSZv8o{$I7dyE@c)DxKRYByN0Gp^WF0rP#aiv`SF z#QY^vx}bL!OZP+hQiWn8%I>|n`o<>iK4=Z(8_Js@k2!DQ7KHxU)gUga?$o0lq9!KIG+_bu>q(T&hI65K%Hb<{|Nhr zdgChlw?nKK4|m!c^!05i=KCGI`D>%EvU?vj-GMhw)N~i#oI?L|t{2x|`Cg8h+b{6e z7kcIUITk(eJJH5|Kj4nseusCb#k5s^m}7_8S99ouJm&Z>h`&Fy)zAO;n0LsR3bM0W z$mJot+_N2!yXgKMBZfQY?`iQNs&@CDhunX6T%C6Ib{C}1SngaO z^)1fh6tcGJ!uLaXeeHc}@!oG?uro70#1l1wya$b!b<66af5 diff --git a/src/shaders/vulkan/Renderable3D_Outline_frag.glsl b/src/shaders/vulkan/Renderable3D_Outline_frag.glsl deleted file mode 100644 index 9a741e482..000000000 --- a/src/shaders/vulkan/Renderable3D_Outline_frag.glsl +++ /dev/null @@ -1,56 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec2 uvNoise; - -layout(location = 0) out vec4 color; - -// ColorMap[0] - ColorMap, ColorMap[1] - NoiseMap -layout(binding = 3) uniform sampler2D ColorMap[4]; - -layout(binding = 0) uniform Character3DScene { - mat4 ViewProjection; - vec4 Tint; - vec3 WorldLightPosition; - vec3 WorldEyePosition; - bool DarkMode; -}; - -layout(binding = 1) uniform Character3DModel { mat4 Model; }; - -layout(binding = 2) uniform Character3DMesh { - mat4 Bones[32]; - float ModelOpacity; - bool HasShadowColorMap; -}; - -layout(push_constant) uniform constants -{ - bool IsDash; -} PushConstants; - -void main() { - vec4 texColor = texture(ColorMap[0], uv); - if (texColor.a <= 0.1) discard; - - if (PushConstants.IsDash) { - vec3 factor1 = vec3(0.70588); - vec3 factor2 = vec3(8.0); - - vec3 c1 = - factor1 * texColor.rgb + clamp(texColor.rgb * factor2, 0.0, 1.0) * 0.25; - // 0.4, 0.2, 0.2 is from mesh info unk9 - vec3 c2 = clamp(c1 + vec3(0.4, 0.2, 0.2) + vec3(-1.0), 0.0, 1.0); - vec3 c3 = -c1 + c2; - - float noiseFactor = texture(ColorMap[1], uvNoise).r; - - color = vec4(c3 * noiseFactor + c1, 1.0); - } else { - const vec4 outlineColor = vec4(0.46484375, 0.27734375, 0.22265625, 1.0); - color = outlineColor * texColor; - } - - color.a *= ModelOpacity; -} \ No newline at end of file diff --git a/src/shaders/vulkan/Renderable3D_Outline_frag.spv b/src/shaders/vulkan/Renderable3D_Outline_frag.spv deleted file mode 100644 index fa1072144a5d7fbb6669f3b8ccefd98cd94cb616..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3872 zcmZve+f!Rr6vj7%0KHp#mx=*KQK{G#deI7nLK~`~q=LoP3xwpfq)l@$2`y-~(AxTB z{}Eq(bjBH<>%Zcwm(dx&-#L51k#Wy_thK(qZu@pZs=24lxhA*6?Q-9_c`>x&C^i)IWIYI3BxQDsseUk85`=lHhKkTxH_0@R_h6ydYoZR76@znVtJZfh}&k z%jV{?Q&ZX8#ku0r(p{W1h0%}NcVml%nj(VQ!1!dKM(G`%aUrY*@p{@Kjx(DKOF?C7sZcC8 zR`F@o9^=p1Ocd(Vi-l5nKe1W#yn>@fS|_XUf$EKGcPy?rd1Alyc=;i;a9(FI!AJ&uxq5FRligv&6SX@tps7p>~ILNmZqk zdyJw%zu!tG`i+*)96d3|Fp}7(G3By4NA6Ac7Q0I}Ju%N+@AUH%%4c_`$8%YE!m&pD zIZyoA2kZrJOGNgvWUDYDOlaQDF&){P=W6+>X+FF$`ZbOkkze~JM;~x4;^@uJonAQO zZh>JoYbAzW)|t?-Ud&GRVqCHpxF!L=5rO{Tte1R(OG(FXKEZLma20``EtVc1i%a&5 z-6b&S+0NH`Hk*75dNIy=rUo4SQG@%Ctbt99CSjkv@as}cN)r8`G|n(198x@av0H?U z{%Y$Z4*rO~R@)_+Ctq@y-JyItG=bj%#qX5N2#h{&?~+dbqx!pB5`Q@A?U7`_pYt~N zgh9T&k{N+|G(=b&u*Wv$E~k|Y+M{Mft;%SXQ*0{esiQAyhq>XGXe z;n(NShxRLLMtY~bc{lM|Tik2X`L4rJ1H0FA0a{HA2V8SvvwZwQ=;oe|$6Z1%4p$=w~ifmiv)(V(}q2_G8a+FZnhQOWr4* zhr<{9spn3sck-}K2KE0Cla|Dn?*Mn&_MAJZe-Zv;4{ou~Y_TV{*fR;6cgFt|H5c`sV5B#uJLCH=Dgt%TSr2 zOVaV-8@2AataR4H9Q(#ygtI;`ONTT6N$GI81ecc%KP6a?SEY|6VEl*T{;&6G@zy)} zh{u!JLEg_N0`KRBKn~u|rvf}S z@8@%YZ>znZIqCSoUsWF7$GiZ~pw4y4dBOTBN~bn9{v`n)JD)&0KJXTEQ+jg$Z^_0F z-s&z&hi4d9mJY|B8h6`s&60WD{5Huu0`d4W&)LxXf+TZ)>gMy_cw4+N`XcTNVVl7H z#jXiU0=&h;CF9A%p07%NDXa*#=j_KX4(k+f& Mu<`pxyKz?d7k^GZwEzGB diff --git a/src/shaders/vulkan/Renderable3D_Outline_vert.glsl b/src/shaders/vulkan/Renderable3D_Outline_vert.glsl deleted file mode 100644 index 3bc9a9f6c..000000000 --- a/src/shaders/vulkan/Renderable3D_Outline_vert.glsl +++ /dev/null @@ -1,69 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Normal; -layout(location = 2) in vec2 UV; -layout(location = 3) in lowp ivec4 BoneIndices; // indices into Mesh.BoneMap -layout(location = 4) in vec4 BoneWeights; - -layout(location = 0) out vec2 uv; -layout(location = 1) out vec2 uvNoise; - -layout(binding = 0) uniform Character3DScene { - mat4 ViewProjection; - vec4 Tint; - vec3 WorldLightPosition; - vec3 WorldEyePosition; - bool DarkMode; -}; - -layout(binding = 1) uniform Character3DModel { highp mat4 Model; }; - -layout(binding = 2) uniform Character3DMesh { - mat4 Bones[32]; - float ModelOpacity; - bool HasShadowColorMap; -}; - -// TODO there's a uniform for this somewhere... -// #if DASH -// const float OutlineThickness = 0.0035; -// #else -// const float OutlineThickness = 0.035; -// #endif - -layout(push_constant) uniform constants -{ - bool IsDash; -} PushConstants; - -void main() { - // Accumulated skinning, thanks - // https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch04.html - mat4 skeletalTransform = Bones[BoneIndices.x] * BoneWeights.x + - Bones[BoneIndices.y] * BoneWeights.y + - Bones[BoneIndices.z] * BoneWeights.z + - Bones[BoneIndices.w] * BoneWeights.w; - - mat4 transform = Model * skeletalTransform; - mat3 normalMatrix = mat3(inverse(transform)); - - vec3 worldNormal = normalMatrix * Normal; - - vec4 viewNormal = normalize(ViewProjection * vec4(worldNormal, 0.0)); - - vec4 worldPosition = transform * vec4(Position, 1.0); - - float OutlineThickness = 0.035; - if (PushConstants.IsDash) { - OutlineThickness = 0.0035; - } - - gl_Position = ViewProjection * worldPosition; - gl_Position += viewNormal * OutlineThickness; - - uv = UV; - - uvNoise = (gl_Position.xy / gl_Position.w) * 0.2; -} \ No newline at end of file diff --git a/src/shaders/vulkan/Renderable3D_Outline_vert.spv b/src/shaders/vulkan/Renderable3D_Outline_vert.spv deleted file mode 100644 index 81b151594dc30e2042621af28cbf8cf7289198a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5588 zcmZ9O`*&1V6~`}RCPApJeL=;V2C!yF z)LI`DsjbqNR;?AS^=(D0TC3Gx^zZSpmTUR>+_@WWJ*=Jc-QWE<`|N#gLf`TY14*(h zS(Us#`CHOkmnX|%61e_sA03+<+t}$&Z@lH!oAkIe>B}7Txr{hh2{}@&H^o;YgUJ2J zDda424mpp!g!J)mIr}RlC?zYC(Xpw~iHXs%ol~{Bxv5U~cq5%^)SKzlbiJL{y7h%r zzZC_)db8G;pDsF-@hH|%P6o)FB%Rr`k#?(%z3pnVb8oAC1g^}zE@dB{skW=NZrZ+i zWIXN6z?L%}Q?jGgOgrrT8B;R_`81#kL}|d6!+)&g4vWx^;B8)o8WH zt8;K=?)e5CS!Mp&7xV6JPSm$OfD`_uZNnQo6e2-kg0y#q-Nu2`?7KxH*+b7l3h zdoC@@mUs2eO|D*Tj90tu`Y{cjEjZe0H>USwMwn7Ivs}%59>8azo*uo(4J3>#UWL6~gtw1->&-4(*1tt|`?udZ#_U0*)u~6!iY&(0mf3e6 zPcK@H@6YTd>?76otoH|UQeUzpV0r(O?AbjF!QS7uS)gDBk~44<^If0c-kExBmRI02 zz*bJ4V6U~Boo=llA*9^jVvI!#3Qg&yCcrs+N+i7iZ73%{LksZ1%-((Iq~|KEKez zew%mi6PL1Ybbet^tKLbIQFOoXeqeZTXE6P zd&rgGMybnua-Qw?vmSAUz7E{8_hsKy*y8t&cQ?-)HL#5HJ5zis+OB7JiEr=03{T|P zd)9Is_YB=yUEV3UxTpE#qJ9TftY6*w?SpmsJJPz;J#&%W6=yDHTHZ6TX9gE%24@ay z+lB;Z9deZd*Ozk#3Y>k>&tEFuVUa!VumoO@xU5;-JGj*Sj=Y1*bK{#ZpUZr5=F=YU zeU(O5aMmx^>qXDc7&&VWKe3!On>)S*Yw=A-E$Y5&b@QnE_b2*&C9M29a+p)R8su9a zLe}7KkJUZv8h-LbGfsU7{dKu6e>J*w4I!=@bNv$V5OOWL-;%y^gY?3;9^Y3lw#47m zUM<=-6Qk~TV11r(Ir|W@4Dk&0D-f48U&$^PHC_eQSKfT;ek&30xvLSEcUr@)t#?i- zSqt`T>(>5ecJ21YeCp9t?bqdY`xZU$Ef^E}Ca^g}9|t>wL4MZQXmR(NWT71veDX)Gs*Y#1qkKMY|&9Ck^DX0Cj?8YmD{9I(WHg#i^nA-`k zbuA+1QeQ&kyr*?Oh`8b`za7sC`)Q5I;vJs-O_1kAAKf2EZn)>NE%xaNaGd=l*taNW zZgu|-$(ifv9P57-6+OcqXFdzwaUk97`}{uGb2cD@py$}525pM@e!y;zwR@iW*__k< zLXM4fPA{^X*IsD<4ZHF3#;g17#@v1jwl85n7If!$CfB!f>KgDh zh~J>!-4<%_Tl4Rg{B~}!mi#Hqd-vc&wd4YQ`*jTxUy&0^pwurq2 zY^?7nxLd)-%0=vLV12b!xUF+|AL3oC$=v#E=Z?OK_an|@6B6^dJ?CQ{o6%z)+F~9b z0BbXsZ(_pdBTf}}4Y^=QxZWL^+T%5ZLtgp84+YL6hIFApZ8(W;mo#^^%i+PNJy^A%OTc4Q6 z9k&k)o1sf+Hce@*GjjrJKf%SDo zU-pCb)fRpq0UKMK$4AkPEzaX(==y4l*pGvaEzaW}bYqM2_yoGX+9LLoU}KB(m_j$U zIFAG9`f7`LRKecGn#_Fw*-F$(c5U`^E&IJlid=z2&kyB%=ricXJwlA%ULDa#-kb+> zF8rJ5a+mP?SN|4bpVlMV;(l{rZLSGC53_#?kyl*C*{6tUgCk$Wbl~I_*Z;?K;fyg) z#LR=`6<5SmsCgEB0kIZy>+3y_u*-W-eU2k?>el{gp#p^+jkK; z|Gy)SbDjnN8!l|_G2b78mykHuZ{bIXy#2Gs&m-0zbNDe>A9?et~J^*?)(e zN3@;G^@#mFdc?+=e}I#ppc}^j5s_0|z7hXMyv+V5B;v=xao<;RTZOvK@n=L%c_`=p a0yeic`=Z}p5&2gU>wPKb{>!PGkpBT9Z28Op diff --git a/src/shaders/vulkan/Sprite_frag.glsl b/src/shaders/vulkan/Sprite_frag.glsl deleted file mode 100644 index e2ac2c279..000000000 --- a/src/shaders/vulkan/Sprite_frag.glsl +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec4 tint; - -layout(location = 0) out vec4 color; - -layout(binding = 0) uniform sampler2D ColorMap; - -void main() { color = tint * texture(ColorMap, uv); } \ No newline at end of file diff --git a/src/shaders/vulkan/Sprite_frag.spv b/src/shaders/vulkan/Sprite_frag.spv deleted file mode 100644 index 16b0355875dd96eb54776f20477ecffdcd56036c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 728 zcmYk2%}&B_5X2V>iXb4OpfNF^cj7^fiP4KOz0`2<;ISd4hbFZUC?r0BFXmHuF>!vS zO}fc;|1&%LRi}ErZ&tCEwe8Gy*0ZV@6StQ|*L(LS>vTT3y}LotF((tE=~}~TiumU& zN=O{YTk;e6k+kGAL@!63&3;r^v!=P8?@p(#_v#1BrN2(U;?R$yB=qOeDh$$S8=`BJ zbWsw-n|WDKm!doy%=};xFII|Rc1fcoRS>RgC$kswZ?ol&bFy7GTQfJWza$|8QxE1| zF!fh*tiaj;aQFJZ=(q)A z=U*{(#V4`sd?;sMFf)5{=7H&XDyQFvs?ZPQXyCtdZm2hX$USQc{|D|*TRh1B0m+s# AqyPW_ diff --git a/src/shaders/vulkan/Sprite_inverted_frag.glsl b/src/shaders/vulkan/Sprite_inverted_frag.glsl deleted file mode 100644 index 4d22c471e..000000000 --- a/src/shaders/vulkan/Sprite_inverted_frag.glsl +++ /dev/null @@ -1,15 +0,0 @@ -#version 450 -#pragma shader_stage(fragment) - -layout(location = 0) in vec2 uv; -layout(location = 1) in vec4 tint; - -layout(location = 0) out vec4 color; - -layout(binding = 0) uniform sampler2D ColorMap; - -void main() { - color = texture(ColorMap, uv); - color.rgb = vec3(1.0) - color.rgb; - color *= tint; -} \ No newline at end of file diff --git a/src/shaders/vulkan/Sprite_inverted_frag.spv b/src/shaders/vulkan/Sprite_inverted_frag.spv deleted file mode 100644 index e38191b60d8a0947ef2f0a0743e98995ea0d8a00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1116 zcmYk4NlODk5QR&VXxxo)UnlMx;z30a6%md-bZit0tNLjX|?M8?iClx4%=celaF)AohOwv3%5xYDXuh$0)`v6ARHySl+Vo z*voU+Brzl_$hKvZ(vs69iZbeK_NBtC4VzyM{7S_y-v!lnJLpDlje5`soAsa;cIwqA z?A6ibQ@XHOZM@dff}9lTyTROFZ8cgQ`JDd7!9b-GG_H)Bn6Y8-~9~Ff+j| zXu4r}^z=_3hnJ)rQ34(PMiUVn{lLt`;r(=k^5NPPj9DS#<1_ zL*H*PIr&Sm>|$KT9>B~xC1cJfspwghp@F|r2fhIudh&BJxQf0QGtVa+JcoDlh7a{4 zzaV2T=x)R@?~05b?BPKiv-8_Q%i&%$aIVHvObxqnH6_K=a3?jMJe;f9P)rT`b2Xca kso{;(pn-Gq?I>oS4(}?a$7iyiJ;iY7+t<8 diff --git a/src/shaders/vulkan/Sprite_inverted_vert.glsl b/src/shaders/vulkan/Sprite_inverted_vert.glsl deleted file mode 100644 index 76e12b560..000000000 --- a/src/shaders/vulkan/Sprite_inverted_vert.glsl +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 UV; -layout(location = 2) in vec4 Tint; -layout(location = 3) in vec2 MaskUV; - -layout(location = 0) out vec2 uv; -layout(location = 1) out vec4 tint; - -void main() { - gl_Position = vec4(Position, 0.0, 1.0); - uv = UV; - tint = Tint; -} diff --git a/src/shaders/vulkan/Sprite_inverted_vert.spv b/src/shaders/vulkan/Sprite_inverted_vert.spv deleted file mode 100644 index 4865111182b449fffe4678f65517178042390227..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1236 zcmYk4OK;Oa6orR4PD@MQG@-PFgmhP_>H-iF0)zm$i&QNtbZbS4g+{n;6gySRir>bs zVuQr_#-7L%-P}3nzON@}43>;}U{=kVIW*3W&4!c>1Uf4qimckY-|JDJWUt2P;;^ePN*OISQKttH))bd*nz(_wns6<(I^ zNjOIpeyBV34}@2wiHGaz#waMW3Meq~b4aKz*LSikTmnJLZt%ub5E!omhIH-iF0)zm$i&QNtbZbS4g+{n;6gySRir>bs zVuQr_#-7L%-P}3nzON@}43>;}U{=kVIW*3W&4!c>1Uf4qimckY-|JDJWUt2P;;^ePN*OISQKttH))bd*nz(_wns6<(I^ zNjOIpeyBV34}@2wiHGaz#waMW3Meq~b4aKz*LSikTmnJLZt%ub5E!omhIW$T@(`QZ@F%UXifyV3$y`c*$9uzAzH?Dyj;4`qFSobJ`*Gc9O ze&NBc&=+#~LT+g(mw&TR+T1ME8xO1HLbXyW7gj4<CXNsYB~<67?W{E6**(-)w@xPEM-{Q1gui)ZLPgon-T(nfV-3zwKo7{T6Nx%t*s z@d4G_S`J&%M0;&fh+)nsLStV2xEf2{(2> z2;qy_Np{o+fm#}e*?9`hczaE+$VcgQhz;Y0$$bEu1ukpJhk>{IDEuJScr|-FgmtN3 zNVxaKWxm7MEU=#W^&rpMyWX|IJPx^KhRv&R*s~?D2A< zsSEFkd(LA4_zu=Khp}Uvcn;gX4_$mW?YXIW&ho`X^PH|EzVQc`{<~Q9t61-jGxs^U z-k|5 z*T2NOw*;!dUi8iF9Bu+71kAS({ zyF^dEx7vC3o!uSa{}6TeJwvrvw}8L9x4UTSF{YTrqT$;7`06fm zAHz-n>t%tp<;KO@&*EGAIIxzrp9AW#_Vf7Z+9#42^;r7_e05i>eG=c=-Z^W_jf=Hk z!ngJ$h_$Ei)no0K@zb?W!HrRmwO_$kcg5PT;#+$fSX*wKc|Et&!2NHNdA^Zo3)ufS IJGtllKc^_fd;kCd diff --git a/src/shaders/vulkan/YUVFrame_vert.glsl b/src/shaders/vulkan/YUVFrame_vert.glsl deleted file mode 100644 index 76e12b560..000000000 --- a/src/shaders/vulkan/YUVFrame_vert.glsl +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 -#pragma shader_stage(vertex) - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec2 UV; -layout(location = 2) in vec4 Tint; -layout(location = 3) in vec2 MaskUV; - -layout(location = 0) out vec2 uv; -layout(location = 1) out vec4 tint; - -void main() { - gl_Position = vec4(Position, 0.0, 1.0); - uv = UV; - tint = Tint; -} diff --git a/src/shaders/vulkan/YUVFrame_vert.spv b/src/shaders/vulkan/YUVFrame_vert.spv deleted file mode 100644 index 4865111182b449fffe4678f65517178042390227..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1236 zcmYk4OK;Oa6orR4PD@MQG@-PFgmhP_>H-iF0)zm$i&QNtbZbS4g+{n;6gySRir>bs zVuQr_#-7L%-P}3nzON@}43>;}U{=kVIW*3W&4!c>1Uf4qimckY-|JDJWUt2P;;^ePN*OISQKttH))bd*nz(_wns6<(I^ zNjOIpeyBV34}@2wiHGaz#waMW3Meq~b4aKz*LSikTmnJLZt%ub5E!omhI Date: Tue, 1 Sep 2026 19:56:18 +0200 Subject: [PATCH 03/60] Add minimum running BGFX rendering backend --- CMakeLists.txt | 53 +++++++++- src/config.h.in | 3 +- src/debugmenu.cpp | 9 +- src/renderer/bgfx/renderer.cpp | 188 +++++++++++++++++++++++++++++++++ src/renderer/bgfx/renderer.h | 138 ++++++++++++++++++++++++ src/renderer/bgfx/window.cpp | 48 +++++++++ src/renderer/bgfx/window.h | 25 +++++ src/renderer/renderer.cpp | 23 +++- src/renderer/renderer.h | 12 +-- src/renderer/window.cpp | 23 +++- src/userconfig.h | 19 +++- 11 files changed, 522 insertions(+), 19 deletions(-) create mode 100644 src/renderer/bgfx/renderer.cpp create mode 100644 src/renderer/bgfx/renderer.h create mode 100644 src/renderer/bgfx/window.cpp create mode 100644 src/renderer/bgfx/window.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 52de35e67..cf0666808 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -824,8 +824,11 @@ if (NX OR EMSCRIPTEN) set(BUILD_SHARED_LIBS OFF) endif () -if (UNIX AND NOT CYGWIN) - set(IMPACTO_DISABLE_DX9 ON) +if (NOT WIN32 AND NOT CYGWIN) + set(IMPACTO_DISABLE_DIRECT3D ON) +endif() +if (NOT APPLE) + set(IMPACTO_DISABLE_METAL ON) endif () if (IMPACTO_ASAN) @@ -1129,9 +1132,38 @@ if (NOT DEFINED IMPACTO_DISABLE_IMGUI) ) endif () - if (NOT DEFINED IMPACTO_DISABLE_DX9) + if (NOT DEFINED IMPACTO_DISABLE_DIRECT3D) + list(APPEND imgui_src + ${imgui_SOURCE_DIR}/backends/imgui_impl_dx12.cpp + ) + endif () + + if (NOT DEFINED IMPACTO_DISABLE_METAL) + list(APPEND imgui_src + ${imgui_SOURCE_DIR}/backends/imgui_impl_metal.mm + ) + endif () + + if (NOT DEFINED IMPACTO_DISABLE_BGFX) + FetchContent_Declare( + imgui_impl_bgfx + URL https://gist.github.com/Madman10K/0ffc9ba203333d3580d467d972bbf8b6/archive/9110d39e126dbd557ad1ff5147526ffeaeb7267c.zip + ) + FetchContent_MakeAvailable(imgui_impl_bgfx) + file(DOWNLOAD + https://raw.githubusercontent.com/pr0g/sdl-bgfx-imgui-starter/8cff6aef7d14a16b820254f646e2f22535925d8d/bgfx-imgui/fs_ocornut_imgui.bin.h + ${imgui_impl_bgfx_SOURCE_DIR}/fs_ocornut_imgui.bin.h + ) + file(DOWNLOAD + https://raw.githubusercontent.com/pr0g/sdl-bgfx-imgui-starter/8cff6aef7d14a16b820254f646e2f22535925d8d/bgfx-imgui/vs_ocornut_imgui.bin.h + ${imgui_impl_bgfx_SOURCE_DIR}/vs_ocornut_imgui.bin.h + ) + list(APPEND imgui_src - ${imgui_SOURCE_DIR}/backends/imgui_impl_dx9.cpp + ${imgui_impl_bgfx_SOURCE_DIR}/imgui_impl_bgfx.cpp + ) + list(APPEND imgui_Include_Dirs + ${imgui_impl_bgfx_SOURCE_DIR} ) endif () @@ -1148,6 +1180,10 @@ if (NOT DEFINED IMPACTO_DISABLE_IMGUI) target_link_libraries(imgui PRIVATE ${SDL3_LIBRARIES} ${OpenGL_Libs}) + if (NOT DEFINED IMPACTO_DISABLE_BGFX) + target_link_libraries(imgui PUBLIC bgfx::bgfx PRIVATE bgfx::bx) + endif () + list(APPEND Impacto_Lib_Targets imgui) endif () @@ -1179,6 +1215,15 @@ endif () if (NOT DEFINED IMPACTO_DISABLE_BGFX) find_package(bgfx CONFIG REQUIRED) list(APPEND Impacto_Libs bgfx::bgfx) + + list(APPEND Impacto_Src + src/renderer/bgfx/renderer.cpp + src/renderer/bgfx/window.cpp + ) + list(APPEND Impacto_Header + src/renderer/bgfx/renderer.h + src/renderer/bgfx/window.h + ) endif() if (NOT DEFINED IMPACTO_DISABLE_FFMPEG) diff --git a/src/config.h.in b/src/config.h.in index acb41956f..45806db62 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -6,8 +6,9 @@ #cmakedefine01 IMPACTO_USE_SDL_HIGHDPI #cmakedefine IMPACTO_DISABLE_BGFX #cmakedefine IMPACTO_DISABLE_VULKAN -#cmakedefine IMPACTO_DISABLE_DX9 #cmakedefine IMPACTO_DISABLE_OPENGL +#cmakedefine IMPACTO_DISABLE_DIRECT3D +#cmakedefine IMPACTO_DISABLE_METAL #cmakedefine IMPACTO_DISABLE_FFMPEG #cmakedefine IMPACTO_DISABLE_OPENAL #cmakedefine IMPACTO_DISABLE_MSPACK diff --git a/src/debugmenu.cpp b/src/debugmenu.cpp index 16619311c..5933fd285 100644 --- a/src/debugmenu.cpp +++ b/src/debugmenu.cpp @@ -763,7 +763,8 @@ static ankerl::unordered_dense::map> SpritesBySpriteSheet; static void ShowSprite(const Sprite* sprite) { - if (UserConfig::AdvancedSettings.ActiveRenderer == RendererType::OpenGL) { + if (UserConfig::AdvancedSettings.ActiveRenderer == + RendererType::OpenGLLegacy) { float texWidth = sprite->Sheet.DesignWidth; float texHeight = sprite->Sheet.DesignHeight; ImGui::Image( @@ -792,7 +793,7 @@ void ShowObjects() { float texHeight = spriteSheet.second.DesignHeight * 0.4f; // Only OpenGL for now if (UserConfig::AdvancedSettings.ActiveRenderer == - RendererType::OpenGL) { + RendererType::OpenGLLegacy) { ImVec2 pos = ImGui::GetCursorScreenPos(); ImGui::Image((ImTextureID)(intptr_t)spriteSheet.second.Texture, ImVec2(texWidth, texHeight)); @@ -842,7 +843,7 @@ void ShowObjects() { float texHeight = Backgrounds[i].BgSprite.Sheet.DesignHeight * 0.4f; // Only OpenGL for now if (UserConfig::AdvancedSettings.ActiveRenderer == - RendererType::OpenGL) { + RendererType::OpenGLLegacy) { ImVec2 pos = ImGui::GetCursorScreenPos(); ImGui::Image( (ImTextureID)(intptr_t)Backgrounds[i].BgSprite.Sheet.Texture, @@ -897,7 +898,7 @@ void ShowObjects() { Characters2D[i].CharaSprite.Sheet.DesignHeight * 0.4f; // Only OpenGL for now if (UserConfig::AdvancedSettings.ActiveRenderer == - RendererType::OpenGL) { + RendererType::OpenGLLegacy) { ImVec2 pos = ImGui::GetCursorScreenPos(); ImGui::Image((ImTextureID)(intptr_t)Characters2D[i] .CharaSprite.Sheet.Texture, diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp new file mode 100644 index 000000000..110d63ce0 --- /dev/null +++ b/src/renderer/bgfx/renderer.cpp @@ -0,0 +1,188 @@ +#include "renderer.h" + +#include "../../log.h" +#include "../../userconfig.h" + +#include +#include + +namespace Impacto::Bgfx { + +constexpr bgfx::ViewId IMGUI_VIEW = 255; + +Renderer::Renderer() { + bgfx::Init initStruct{}; + + initStruct.type = []() -> bgfx::RendererType::Enum { + switch (UserConfig::AdvancedSettings.ActiveRenderer) { +#ifndef IMPACTO_DISABLE_OPENGL + case RendererType::OpenGL: + return bgfx::RendererType::OpenGL; + case RendererType::OpenGLES: + return bgfx::RendererType::OpenGLES; +#endif +#ifndef IMPACTO_DISABLE_VULKAN + case RendererType::Vulkan: + return bgfx::RendererType::Vulkan; +#endif +#ifndef IMPACTO_DISABLE_DIRECT3D + case RendererType::Direct3D: + return bgfx::RendererType::Direct3D12; +#endif +#ifndef IMPACTO_DISABLE_METAL + case RendererType::Metal: + return bgfx::RendererType::Metal; +#endif + + default: + assert(false && "Unsupported bgfx render type"); + return bgfx::RendererType::Count; // Have bgfx choose + } + }(); + ImpLog(LogLevel::Info, LogChannel::Render, + "Initializing BGFX with {:s} backend", + magic_enum::enum_name(initStruct.type)); + + initStruct.resolution.width = UserConfig::CommonSettings.ResolutionWidth; + initStruct.resolution.height = UserConfig::CommonSettings.ResolutionHeight; + initStruct.resolution.reset = BGFX_RESET_VSYNC; +#if defined(SDL_PLATFORM_WIN32) + initStruct.platformData.nwh = + SDL_GetPointerProperty(SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); +#elif defined(SDL_PLATFORM_LINUX) + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + initStruct.platformData.ndt = + SDL_GetPointerProperty(SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr); + initStruct.platformData.nwh = std::bit_cast( + SDL_GetNumberProperty(SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0)); + } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { + initStruct.platformData.ndt = SDL_GetPointerProperty( + SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr); + initStruct.platformData.nwh = SDL_GetPointerProperty( + SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr); + } else { + const std::string errorMsg = fmt::format( + "Unsupported video driver \"{:s}\"", SDL_GetCurrentVideoDriver()); + ImpLog(LogLevel::Fatal, LogChannel::Render, "{:s}", errorMsg); + throw std::runtime_error(errorMsg); + } +#elif defined(SDL_PLATFORM_ANDROID) + initStruct.platformData.nwh = + SDL_GetPointerProperty(SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr); +#elif defined(SDL_PLATFORM_MACOS) + initStruct.platformData.nwh = + SDL_GetPointerProperty(SDL_GetWindowProperties(Window->SDLWindow), + SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr); +#else + static_assert(false && "We have not implemented BGFX for this platform"); +#endif + +#if IMPACTO_GL_DEBUG + initStruct.debug = true; +#else + initStruct.debug = false; +#endif + + if (!bgfx::init(initStruct)) { + constexpr const char* errorMsg = "Failed to initialize BGFX"; + ImpLog(LogLevel::Fatal, LogChannel::Render, errorMsg); + throw std::runtime_error(errorMsg); + } + + Indices.resize(100); + IndexBuffer = bgfx::createDynamicIndexBuffer( + static_cast(Indices.size()), BGFX_BUFFER_ALLOW_RESIZE); + if (!bgfx::isValid(IndexBuffer)) { + constexpr const char* errorMsg = "Failed to create index buffer"; + ImpLog(LogLevel::Fatal, LogChannel::Render, errorMsg); + throw std::runtime_error(errorMsg); + } + + VertexBufferSpritesLayout.begin() + .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float) + .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Float, true) + .add(bgfx::Attrib::TexCoord1, 2, bgfx::AttribType::Float) + .end(); + + Vertices.resize(100); + VertexBuffer = bgfx::createDynamicVertexBuffer( + bgfx::copy( + Vertices.data(), + static_cast(Vertices.size() * sizeof(VertexBufferSprites))), + VertexBufferSpritesLayout); + if (!bgfx::isValid(VertexBuffer)) { + constexpr const char* errorMsg = "Failed to create vertex buffer"; + ImpLog(LogLevel::Fatal, LogChannel::Render, errorMsg); + throw std::runtime_error(errorMsg); + } + + ImGui_Implbgfx_Init(IMGUI_VIEW); + switch (UserConfig::AdvancedSettings.ActiveRenderer) { +#ifndef IMPACTO_DISABLE_OPENGL + case RendererType::OpenGL: + case RendererType::OpenGLES: + ImGui_ImplSDL3_InitForOpenGL(Window->SDLWindow, nullptr); + break; +#endif +#ifndef IMPACTO_DISABLE_VULKAN + case RendererType::Vulkan: + ImGui_ImplSDL3_InitForVulkan(Window->SDLWindow); + break; +#endif +#ifndef IMPACTO_DISABLE_DIRECT3D + case RendererType::Direct3D: + ImGui_ImplSDL3_InitForD3D(Window->SDLWindow); + break; +#endif +#ifndef IMPACTO_DISABLE_METAL + case RendererType::Metal: + ImGui_ImplSDL3_InitForMetal(Window->SDLWindow); + break; +#endif + + default: + assert(false); + break; + } +} + +void Renderer::BeginFrame() {} + +void Renderer::BeginFrame2D() { + bgfx::reset(UserConfig::CommonSettings.ResolutionWidth, + UserConfig::CommonSettings.ResolutionHeight, BGFX_RESET_VSYNC); +} + +void Renderer::EndFrame() {} + +#ifndef IMPACTO_DISABLE_IMGUI +void Renderer::ImGuiBeginFrame() { + ImGui_Implbgfx_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + + bgfx::touch(IMGUI_VIEW); +} +#endif + +void Renderer::Shutdown() { + bgfx::destroy(IndexBuffer); + bgfx::destroy(VertexBuffer); + +#ifndef IMPACTO_DISABLE_IMGUI + ImGui_ImplSDL3_Shutdown(); + ImGui_Implbgfx_Shutdown(); + ImGui::DestroyContext(); +#endif + + bgfx::shutdown(); +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h new file mode 100644 index 000000000..8517f3d9b --- /dev/null +++ b/src/renderer/bgfx/renderer.h @@ -0,0 +1,138 @@ +#pragma once + +#include "../renderer.h" + +#include + +namespace Impacto::Bgfx { + +class Renderer final : public BaseRenderer { + public: + Renderer(); + ~Renderer() = default; + void Init() override {} + void Shutdown() override; + +#ifndef IMPACTO_DISABLE_IMGUI + void ImGuiBeginFrame() override; +#endif + + void BeginFrame() override; + void BeginFrame2D() override; + void EndFrame() override; + + uint32_t MapSpriteSheet(SpriteSheet const& sheet) override { return 0; } + bool LoadSurf(int surfId, int archiveId, int fileId) override { return true; } + void UnloadSurf(int surfId) override {} + uint32_t SubmitTexture(TexFmt format, uint8_t* buffer, int width, + int height) override { + return 0; + } + + int GetSpriteSheetImage(SpriteSheet const& sheet, + std::span outBuffer) override { + return 0; + } + void FreeTexture(uint32_t id) override {} + YUVFrame* CreateYUVFrame(float width, float height) override { + return nullptr; + } + NV12Frame* CreateNV12Frame(float width, float height) override { + return nullptr; + } + + void DrawSprite(Sprite const& sprite, CornersQuad const& dest, + glm::mat4 transformation, std::span tints, + glm::vec3 colorShift, bool inverted, bool disableBlend, + bool textureWrapRepeat) override {} + + void DrawMaskedSprite(Sprite const& sprite, Sprite const& mask, + CornersQuad const& spriteDest, + CornersQuad const& maskDest, int alpha, int fadeRange, + glm::mat4 spriteTransformation, + glm::mat4 maskTransformation, + std::span tints, bool isInverted, + bool isSameTexture) override {} + + void DrawMaskedBinarySprite(Sprite const& sprite, Sprite const& mask, + CornersQuad const& spriteDest, + CornersQuad const& maskDest, + glm::mat4 spriteTransformation, + std::optional maskTransformation, + std::span tints, + bool isInverted) override {} + + void DrawMaskedSpriteOverlay(Sprite const& sprite, Sprite const& mask, + CornersQuad const& spriteDest, + CornersQuad const& maskDest, int alpha, + int fadeRange, glm::mat4 spriteTransformation, + glm::mat4 maskTransformation, + std::span tints, + bool isInverted, bool useMaskAlpha) override {} + + void DrawPrimitives(SpriteSheet const& sheet, SpriteSheet const* mask, + ShaderProgramType shaderType, + std::span vertices, + std::span indices, + glm::mat4 spriteTransformation, + glm::mat4 maskTransformation, bool inverted, + TopologyMode topology, bool textureWrapRepeat) override {} + + void DrawCCMessageBox(Sprite const& sprite, Sprite const& mask, + RectF const& dest, glm::vec4 tint, int alpha, + int fadeRange, float effectCt) override {} + + void DrawEdgeDetectedSingleSheetFont( + SpriteSheet const& sheet, SpriteSheet const* mask, + std::span vertices, + std::span indices, float differenceFactor, + float intensityShift, float alphaShift, glm::vec2 renderScale, + glm::mat4 spriteTransformation, glm::mat4 maskTransformation) override {} + + void DrawCHLCCMenuBackground(Sprite const& sprite, Sprite const& mask, + RectF const& dest, float alpha) override {} + + void DrawBlurredSprite(Sprite const& sprite, CornersQuad const& dest, + glm::mat4 transformation, + RendererBlurDirection blurDirection, + glm::vec4 tint) override {} + + void DrawMosaic(Sprite const& sprite, CornersQuad dest, float tileSize, + glm::mat4 transformation, glm::vec4 tint) override {} + + void DrawVideoTexture(YUVFrame const& frame, RectF const& dest, + glm::vec4 tint, bool alphaVideo) override {} + void DrawVideoTexture(NV12Frame const& frame, RectF const& dest, + glm::vec4 tint, bool alphaVideo) override {} + + void DrawSubtitleGlyph(Sprite const& sprite, CornersQuad const& dest, + glm::mat4 transformation, glm::vec4 tint) override {} + + void CaptureScreencap(Sprite& sprite) override {} + + void SetFramebuffer(size_t buffer) override {} + int GetFramebufferTexture(size_t buffer) override { return 0; } + + void EnableScissor() override {} + void SetScissorRect(RectF const& rect) override {} + void DisableScissor() override {} + + void SetStencilMode(StencilBufferMode mode) override {} + void ClearStencilBuffer() override {} + + void SetBlendMode(RendererBlendMode blendMode) override {} + + void Clear(glm::vec4 color) override {} + + private: + void Flush() override {} + + bgfx::DynamicIndexBufferHandle IndexBuffer; + bgfx::DynamicVertexBufferHandle VertexBuffer; + std::vector Indices; + std::vector Vertices; + + bgfx::VertexLayout VertexBufferSpritesLayout; +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/window.cpp b/src/renderer/bgfx/window.cpp new file mode 100644 index 000000000..b26fe95d8 --- /dev/null +++ b/src/renderer/bgfx/window.cpp @@ -0,0 +1,48 @@ +#include "window.h" + +#include "../../log.h" +#include "../../userconfig.h" + +#include +#include + +#ifndef IMPACTO_DISABLE_IMGUI +#include +#include +#endif // IMPACTO_DISABLE_IMGUI + +namespace Impacto::Bgfx { + +void Window::Init() { + ImpLog(LogLevel::Info, LogChannel::General, "Creating bgfx window\n"); + + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { + std::string errorMsg = + fmt::format("SDL initialization failed: {:s}\n", SDL_GetError()); + ImpLog(LogLevel::Fatal, LogChannel::General, "{:s}", errorMsg); + throw std::runtime_error(errorMsg); + } + +#ifdef SDL_PLATFORM_ANDROID + SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); +#endif + + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); + + uint32_t windowFlags = 0; + if (!CreateSDLWindow(windowFlags)) { + Panic(LogChannel::General, "Failed to create SDL window: {:s}\n", + SDL_GetError()); + } +} + +void Window::Draw() { +#ifndef IMPACTO_DISABLE_IMGUI + ImGui::Render(); + ImGui_Implbgfx_RenderDrawLists(ImGui::GetDrawData()); +#endif + + bgfx::frame(); +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/window.h b/src/renderer/bgfx/window.h new file mode 100644 index 000000000..18dae2990 --- /dev/null +++ b/src/renderer/bgfx/window.h @@ -0,0 +1,25 @@ +#pragma once + +#include "../window.h" + +namespace Impacto::Bgfx { + +class Window final : public BaseWindow { + public: + void Init() override; + + void SetDimensions(int width, int height, int msaa, + float renderScale) override {}; + + void Update() override {} + + void SwapRTs() override {} + void Draw() override; + + void Shutdown() override {} + + private: + void UpdateDimensions() override {} +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 39816bbbf..508b1a5ee 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -8,6 +8,10 @@ #include "opengl/renderer.h" #endif +#ifndef IMPACTO_DISABLE_BGFX +#include "bgfx/renderer.h" +#endif + #include namespace Impacto { @@ -15,10 +19,27 @@ namespace Impacto { void CreateRenderer() { switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL - case RendererType::OpenGL: + case RendererType::OpenGLLegacy: Renderer = new OpenGL::Renderer(); break; #endif +#ifndef IMPACTO_DISABLE_BGFX +#ifndef IMPACTO_DISABLE_OPENGL + case RendererType::OpenGL: + case RendererType::OpenGLES: +#endif +#ifndef IMPACTO_DISABLE_VULKAN + case RendererType::Vulkan: +#endif +#ifndef IMPACTO_DISABLE_DIRECT3D + case RendererType::Direct3D: +#endif +#ifndef IMPACTO_DISABLE_METAL + case RendererType::Metal: +#endif + Renderer = new Bgfx::Renderer(); + break; +#endif // IMPACTO_DISABLE_BGFX default: ImpLog(LogLevel::Error, LogChannel::Render, "Unknown or unsupported renderer selected!\n"); diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 408dbd1ce..eecd91f78 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -309,13 +309,11 @@ class BaseRenderer { TopologyMode topology = TopologyMode::Triangles, bool textureWrapRepeat = false) = 0; - virtual void DrawPrimitives(const SpriteSheet& sheet, - ShaderProgramType shaderType, - std::span vertices, - std::span indices, - glm::mat4 transformation = glm::mat4(1.0f), - bool inverted = false, - bool textureWrapRepeat = false) { + void DrawPrimitives(const SpriteSheet& sheet, ShaderProgramType shaderType, + std::span vertices, + std::span indices, + glm::mat4 transformation = glm::mat4(1.0f), + bool inverted = false, bool textureWrapRepeat = false) { DrawPrimitives(sheet, nullptr, shaderType, vertices, indices, transformation, glm::mat4(1.0f), inverted, TopologyMode::Triangles, textureWrapRepeat); diff --git a/src/renderer/window.cpp b/src/renderer/window.cpp index d4d8604e4..e2c930ec9 100644 --- a/src/renderer/window.cpp +++ b/src/renderer/window.cpp @@ -11,14 +11,35 @@ #include "../inputsystem.h" #include "opengl/window.h" +#ifndef IMPACTO_DISABLE_BGFX +#include "bgfx/window.h" +#endif + namespace Impacto { void InitWindow() { switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL - case RendererType::OpenGL: + case RendererType::OpenGLLegacy: Window = new OpenGL::GLWindow(); break; +#endif +#ifndef IMPACTO_DISABLE_BGFX +#ifndef IMPACTO_DISABLE_OPENGL + case RendererType::OpenGL: + case RendererType::OpenGLES: +#endif +#ifndef IMPACTO_DISABLE_VULKAN + case RendererType::Vulkan: +#endif +#ifndef IMPACTO_DISABLE_DIRECT3D + case RendererType::Direct3D: +#endif +#ifndef IMPACTO_DISABLE_METAL + case RendererType::Metal: +#endif + Window = new Bgfx::Window(); + break; #endif default: ImpLog(LogLevel::Error, LogChannel::Render, diff --git a/src/userconfig.h b/src/userconfig.h index e25e864ad..fb570fc68 100644 --- a/src/userconfig.h +++ b/src/userconfig.h @@ -9,8 +9,25 @@ namespace Impacto { enum class RendererType : int { +#ifndef IMPACTO_DISABLE_BGFX +#ifndef IMPACTO_DISABLE_OPENGL OpenGL, - Bgfx, + OpenGLES, +#endif +#ifndef IMPACTO_DISABLE_VULKAN + Vulkan, +#endif +#ifndef IMPACTO_DISABLE_DIRECT3D + Direct3D, +#endif +#ifndef IMPACTO_DISABLE_METAL + Metal, +#endif +#endif + +#ifndef IMPACTO_DISABLE_OPENGL + OpenGLLegacy, +#endif }; enum class VideoPlayerType : int { From 9437305465cedb343d914808bc9f56721592a76e Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 1 Sep 2026 21:02:25 +0200 Subject: [PATCH 04/60] Implement window resizing --- src/renderer/bgfx/window.cpp | 37 ++++++++++++++++++++++++++++++++++++ src/renderer/bgfx/window.h | 8 ++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/renderer/bgfx/window.cpp b/src/renderer/bgfx/window.cpp index b26fe95d8..e423a0125 100644 --- a/src/renderer/bgfx/window.cpp +++ b/src/renderer/bgfx/window.cpp @@ -36,6 +36,13 @@ void Window::Init() { } } +void Window::Shutdown() { + SDL_DestroyWindow(SDLWindow); + SDL_Quit(); + // TODO: move exit to users + exit(0); +} + void Window::Draw() { #ifndef IMPACTO_DISABLE_IMGUI ImGui::Render(); @@ -45,4 +52,34 @@ void Window::Draw() { bgfx::frame(); } +void Window::Update() { UpdateDimensions(); } + +void Window::SetDimensions(int width, int height, int msaa, float renderScale) { + ImpLog(LogLevel::Info, LogChannel::General, + "Attempting to change window dimensions to {:d} x {:d}, {:d}x MSAA, " + "render scale {:f}\n", + width, height, msaa, renderScale); + assert(width > 0 && height > 0 && msaa >= 0 && renderScale > 0.0f); + + SDL_SetWindowSize(SDLWindow, width, height); + + MsaaCount = msaa; + RenderScale = renderScale; +} + +void Window::UpdateDimensions() { + WindowDimensionsChanged = false; + + SDL_GetWindowSizeInPixels(SDLWindow, &WindowWidth, &WindowHeight); + if (WindowWidth != lastWidth || WindowHeight != lastHeight) { + WindowDimensionsChanged = true; + ImpLog(LogLevel::Debug, LogChannel::General, + "Drawable size (pixels): {:d} x {:d}\n", WindowWidth, WindowHeight); + } + lastWidth = WindowWidth; + lastHeight = WindowHeight; + + DpiScale = SDL_GetWindowDisplayScale(SDLWindow); +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/window.h b/src/renderer/bgfx/window.h index 18dae2990..e175e81b6 100644 --- a/src/renderer/bgfx/window.h +++ b/src/renderer/bgfx/window.h @@ -9,17 +9,17 @@ class Window final : public BaseWindow { void Init() override; void SetDimensions(int width, int height, int msaa, - float renderScale) override {}; + float renderScale) override; - void Update() override {} + void Update() override; void SwapRTs() override {} void Draw() override; - void Shutdown() override {} + void Shutdown() override; private: - void UpdateDimensions() override {} + void UpdateDimensions() override; }; } // namespace Impacto::Bgfx From 638b7536679572a6ddd1a1a6122c37f17c12416d Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Thu, 3 Sep 2026 18:07:08 +0200 Subject: [PATCH 05/60] Implement framebuffers and viewport resizing --- CMakeLists.txt | 2 + src/renderer/bgfx/framebuffer.cpp | 75 +++++++++++++++++++++++++++++++ src/renderer/bgfx/framebuffer.h | 52 +++++++++++++++++++++ src/renderer/bgfx/renderer.cpp | 50 +++++++++++++++++++-- src/renderer/bgfx/renderer.h | 11 ++++- 5 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 src/renderer/bgfx/framebuffer.cpp create mode 100644 src/renderer/bgfx/framebuffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cf0666808..a089ebb30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1217,10 +1217,12 @@ if (NOT DEFINED IMPACTO_DISABLE_BGFX) list(APPEND Impacto_Libs bgfx::bgfx) list(APPEND Impacto_Src + src/renderer/bgfx/framebuffer.cpp src/renderer/bgfx/renderer.cpp src/renderer/bgfx/window.cpp ) list(APPEND Impacto_Header + src/renderer/bgfx/framebuffer.h src/renderer/bgfx/renderer.h src/renderer/bgfx/window.h ) diff --git a/src/renderer/bgfx/framebuffer.cpp b/src/renderer/bgfx/framebuffer.cpp new file mode 100644 index 000000000..06848bf43 --- /dev/null +++ b/src/renderer/bgfx/framebuffer.cpp @@ -0,0 +1,75 @@ +#include "framebuffer.h" + +#include + +namespace Impacto::Bgfx { + +FrameBuffer::FrameBuffer(FrameBuffer&& other) { *this = std::move(other); } + +FrameBuffer& FrameBuffer::operator=(FrameBuffer&& other) { + if (&other == this) return *this; + Reset(true); + if (!other.IsInit) return *this; + + IsInit = true; + FrameBufferHandle = other.FrameBufferHandle; + ColorAttachment = other.ColorAttachment; + DepthStencilAttachment = other.DepthStencilAttachment; + + other.Reset(false); + + return *this; +} + +FrameBuffer::~FrameBuffer() { Reset(true); } + +FrameBuffer::FrameBuffer(const uint16_t width, const uint16_t height) + : ColorAttachment(bgfx::createTexture2D(width, height, false, 1, + bgfx::TextureFormat::RGBA8, + BGFX_TEXTURE_RT)), + DepthStencilAttachment(bgfx::createTexture2D(width, height, false, 1, + bgfx::TextureFormat::D24S8, + BGFX_TEXTURE_RT)) { + assert(bgfx::isValid(ColorAttachment)); + assert(bgfx::isValid(*DepthStencilAttachment)); + + std::array attachments; + attachments[0].init(ColorAttachment); + attachments[1].init(*DepthStencilAttachment); + + FrameBufferHandle = bgfx::createFrameBuffer( + static_cast(attachments.size()), attachments.data(), true); + assert(bgfx::isValid(FrameBufferHandle)); + + IsInit = true; +} + +FrameBuffer FrameBuffer::CreateBackBufferFrameBuffer() { + FrameBuffer frameBuffer; + + frameBuffer.ColorAttachment = + bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, + bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT); + assert(bgfx::isValid(frameBuffer.ColorAttachment)); + + frameBuffer.FrameBufferHandle = + bgfx::createFrameBuffer(1, &frameBuffer.ColorAttachment, true); + assert(bgfx::isValid(frameBuffer.FrameBufferHandle)); + + frameBuffer.IsInit = true; + + return frameBuffer; +} + +void FrameBuffer::Reset(bool cleanUpResources) { + if (!IsInit) return; + IsInit = false; + + DepthStencilAttachment.reset(); + + if (cleanUpResources) { + bgfx::destroy(FrameBufferHandle); + } +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/framebuffer.h b/src/renderer/bgfx/framebuffer.h new file mode 100644 index 000000000..42a4d0001 --- /dev/null +++ b/src/renderer/bgfx/framebuffer.h @@ -0,0 +1,52 @@ +#pragma once + +#include + +#include +#include +#include + +namespace Impacto::Bgfx { + +class FrameBuffer { + public: + FrameBuffer() = default; + FrameBuffer(const FrameBuffer&) = delete; + FrameBuffer(FrameBuffer&&); + ~FrameBuffer(); + + FrameBuffer& operator=(const FrameBuffer&) = delete; + FrameBuffer& operator=(FrameBuffer&&); + + FrameBuffer(uint16_t width, uint16_t height); + + [[nodiscard]] static FrameBuffer CreateBackBufferFrameBuffer(); + + operator bgfx::FrameBufferHandle() { return GetFrameBufferHandle(); } + + [[nodiscard]] bgfx::FrameBufferHandle GetFrameBufferHandle() { + assert(IsInit && bgfx::isValid(FrameBufferHandle)); + return FrameBufferHandle; + } + + [[nodiscard]] bgfx::TextureHandle GetColorAttachmentHandle() { + assert(IsInit && bgfx::isValid(ColorAttachment)); + return ColorAttachment; + } + + [[nodiscard]] bgfx::TextureHandle GetTexture() { + assert(IsInit && bgfx::isValid(FrameBufferHandle)); + return bgfx::getTexture(FrameBufferHandle, 0); + } + + private: + bool IsInit = false; + + bgfx::FrameBufferHandle FrameBufferHandle; + bgfx::TextureHandle ColorAttachment; + std::optional DepthStencilAttachment; + + void Reset(bool cleanUpResources); +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 110d63ce0..74b47b063 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -5,9 +5,12 @@ #include #include +#include namespace Impacto::Bgfx { +constexpr bgfx::ViewId RENDER_VIEW = 0; // Uses render dimensions +constexpr bgfx::ViewId DISPLAY_VIEW = 1; // Uses viewport dimensions constexpr bgfx::ViewId IMGUI_VIEW = 255; Renderer::Renderer() { @@ -95,6 +98,13 @@ Renderer::Renderer() { throw std::runtime_error(errorMsg); } + BackBufferFrameBuffer = FrameBuffer::CreateBackBufferFrameBuffer(); + + ViewMatrix = glm::mat4(1.0f); + BackBufferProjectionMatrix = glm::ortho( + 0.0f, static_cast(UserConfig::CommonSettings.ResolutionWidth), + static_cast(UserConfig::CommonSettings.ResolutionHeight), 0.0f); + Indices.resize(100); IndexBuffer = bgfx::createDynamicIndexBuffer( static_cast(Indices.size()), BGFX_BUFFER_ALLOW_RESIZE); @@ -153,11 +163,45 @@ Renderer::Renderer() { } } -void Renderer::BeginFrame() {} +void Renderer::Init() { + DrawFrameBuffer = + FrameBuffer(static_cast(Profile::Game::DesignWidth), + static_cast(Profile::Game::DesignHeight)); + + ProjectionMatrix = + glm::ortho(0.0f, Profile::Game::DesignWidth, Profile::Game::DesignHeight, + 0.0f, -Profile::Game::DesignWidth, Profile::Game::DesignWidth); +} + +void Renderer::BeginFrame() { + bgfx::reset(static_cast(Window->WindowWidth), + static_cast(Window->WindowHeight), BGFX_RESET_VSYNC); + + constexpr uint32_t black = 0xff000000; + bgfx::setViewClear(DISPLAY_VIEW, BGFX_CLEAR_COLOR, black); + bgfx::setViewRect(DISPLAY_VIEW, 0, 0, + static_cast(Window->WindowWidth), + static_cast(Window->WindowHeight)); + bgfx::setViewTransform(DISPLAY_VIEW, glm::value_ptr(ViewMatrix), + glm::value_ptr(BackBufferProjectionMatrix)); + bgfx::setViewFrameBuffer(DISPLAY_VIEW, BackBufferFrameBuffer); + + bgfx::touch(DISPLAY_VIEW); +} void Renderer::BeginFrame2D() { - bgfx::reset(UserConfig::CommonSettings.ResolutionWidth, - UserConfig::CommonSettings.ResolutionHeight, BGFX_RESET_VSYNC); + constexpr uint32_t transparentWhite = 0x00FFFFFF; + bgfx::setViewClear(RENDER_VIEW, + BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, + transparentWhite); + bgfx::setViewRect(RENDER_VIEW, 0, 0, + static_cast(Profile::Game::DesignWidth), + static_cast(Profile::Game::DesignHeight)); + bgfx::setViewTransform(RENDER_VIEW, glm::value_ptr(ViewMatrix), + glm::value_ptr(ProjectionMatrix)); + bgfx::setViewFrameBuffer(RENDER_VIEW, DrawFrameBuffer); + + bgfx::touch(RENDER_VIEW); } void Renderer::EndFrame() {} diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 8517f3d9b..549237e0c 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -2,7 +2,7 @@ #include "../renderer.h" -#include +#include "framebuffer.h" namespace Impacto::Bgfx { @@ -10,7 +10,7 @@ class Renderer final : public BaseRenderer { public: Renderer(); ~Renderer() = default; - void Init() override {} + void Init() override; void Shutdown() override; #ifndef IMPACTO_DISABLE_IMGUI @@ -127,12 +127,19 @@ class Renderer final : public BaseRenderer { private: void Flush() override {} + FrameBuffer BackBufferFrameBuffer; + FrameBuffer DrawFrameBuffer; + bgfx::DynamicIndexBufferHandle IndexBuffer; bgfx::DynamicVertexBufferHandle VertexBuffer; std::vector Indices; std::vector Vertices; bgfx::VertexLayout VertexBufferSpritesLayout; + + glm::mat4 ViewMatrix; + glm::mat4 ProjectionMatrix; + glm::mat4 BackBufferProjectionMatrix; }; } // namespace Impacto::Bgfx From c910e815a090ca44b566e18ec330b48a5cce8c50 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Fri, 4 Sep 2026 21:16:20 +0200 Subject: [PATCH 06/60] Compile bgfx shaders using CMake --- CMakeLists.txt | 40 ++++++++++++++++++++++---- src/shaders/bgfx/source/fs_sprite.sc | 11 +++++++ src/shaders/bgfx/source/varying.def.sc | 8 ++++++ src/shaders/bgfx/source/vs_sprite.sc | 11 +++++++ vcpkg.json | 10 ++++++- 5 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 src/shaders/bgfx/source/fs_sprite.sc create mode 100644 src/shaders/bgfx/source/varying.def.sc create mode 100644 src/shaders/bgfx/source/vs_sprite.sc diff --git a/CMakeLists.txt b/CMakeLists.txt index a089ebb30..16f6ec373 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1226,6 +1226,28 @@ if (NOT DEFINED IMPACTO_DISABLE_BGFX) src/renderer/bgfx/renderer.h src/renderer/bgfx/window.h ) + + set(Bgfx_Vertex_Shaders + src/shaders/bgfx/source/vs_sprite.sc + ) + set(Bgfx_Fragment_Shaders + src/shaders/bgfx/source/fs_sprite.sc + ) + + bgfx_compile_shaders( + TYPE VERTEX + SHADERS ${Bgfx_Vertex_Shaders} + VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/bgfx/source/varying.def.sc + OUTPUT_DIR src/shaders/bgfx + ) + bgfx_compile_shaders( + TYPE FRAGMENT + SHADERS ${Bgfx_Fragment_Shaders} + VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/bgfx/source/varying.def.sc + OUTPUT_DIR src/shaders/bgfx + ) + + list(APPEND Impacto_Src ${Bgfx_Vertex_Shaders} ${Bgfx_Fragment_Shaders}) endif() if (NOT DEFINED IMPACTO_DISABLE_FFMPEG) @@ -1439,8 +1461,10 @@ elseif(APPLE) RUNTIME DESTINATION . RESOURCE DESTINATION . ) - install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/shaders" + install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/shaders" "${PROJECT_BINARY_DIR}/src/shaders" DESTINATION "Impacto.app/Contents/Resources/" + PATTERN "bgfx/source" EXCLUDE ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/resources" DESTINATION "Impacto.app/Contents/Resources/" @@ -1472,7 +1496,11 @@ endif () if (NOT ANDROID) if(NOT APPLE) - install(DIRECTORY src/shaders DESTINATION .) + install( + DIRECTORY src/shaders ${PROJECT_BINARY_DIR}/src/shaders + DESTINATION . + PATTERN "bgfx/source" EXCLUDE + ) install(DIRECTORY resources DESTINATION .) endif() install(DIRECTORY profiles DESTINATION .) @@ -1484,10 +1512,12 @@ if (NOT ANDROID) install(FILES ${CMAKE_SOURCE_DIR}/basepaths.lua.sample DESTINATION . RENAME basepaths.lua) endif() else() - install(DIRECTORY src/shaders DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets) + install( + DIRECTORY src/shaders ${PROJECT_BINARY_DIR}/src/shaders + DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets + PATTERN "bgfx/source" EXCLUDE + ) install(DIRECTORY profiles DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets) install(DIRECTORY resources DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets PATTERN "*/gamedata/*" EXCLUDE) install(FILES gamedefinitions.lua DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets) endif() - - diff --git a/src/shaders/bgfx/source/fs_sprite.sc b/src/shaders/bgfx/source/fs_sprite.sc new file mode 100644 index 000000000..b28c8c922 --- /dev/null +++ b/src/shaders/bgfx/source/fs_sprite.sc @@ -0,0 +1,11 @@ +$input v_texcoord0, v_color0 + +#include + +SAMPLER2D(s_texture, 0); +uniform vec4 u_colorShift; + +void main() { + gl_FragColor = texture2D(s_texture, v_texcoord0) * v_color0; + gl_FragColor.rgb = clamp(gl_FragColor.rgb + u_colorShift.rgb, 0.0f, 1.0f); +} diff --git a/src/shaders/bgfx/source/varying.def.sc b/src/shaders/bgfx/source/varying.def.sc new file mode 100644 index 000000000..3595a2a76 --- /dev/null +++ b/src/shaders/bgfx/source/varying.def.sc @@ -0,0 +1,8 @@ +vec2 v_texcoord0: TEXCOORD0 = vec2_splat(0.0f); +vec4 v_color0: COLOR0 = vec4_splat(1.0f); +vec2 v_texcoord1: TEXCOORD1 = vec2_splat(0.0f); + +vec2 a_position: POSITION; +vec2 a_texcoord0: TEXCOORD0; +vec4 a_color0: COLOR0; +vec2 a_texcoord1: TEXCOORD1; diff --git a/src/shaders/bgfx/source/vs_sprite.sc b/src/shaders/bgfx/source/vs_sprite.sc new file mode 100644 index 000000000..5d5990585 --- /dev/null +++ b/src/shaders/bgfx/source/vs_sprite.sc @@ -0,0 +1,11 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +#include + +void main() { + gl_Position = mul(u_proj, vec4(a_position, 0.0f, 1.0f)); + + v_texcoord0 = a_texcoord0; + v_color0 = a_color0; +} diff --git a/vcpkg.json b/vcpkg.json index 64386a5fe..af3269bbd 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -53,7 +53,15 @@ "toml11", "freetype", "harfbuzz", - "bgfx" + "bgfx", + { + "name": "bgfx", + "host": true, + "default-features": false, + "features": [ + "tools" + ] + } ], "overrides": [ { From fcdc67ea91c86983876d0b68faf10f4df5e582db Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Fri, 4 Sep 2026 22:49:52 +0200 Subject: [PATCH 07/60] Implement basic shader class --- CMakeLists.txt | 2 + src/renderer/bgfx/renderer.cpp | 3 + src/renderer/bgfx/renderer.h | 6 ++ src/renderer/bgfx/shader.cpp | 120 +++++++++++++++++++++++++++++++++ src/renderer/bgfx/shader.h | 47 +++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 src/renderer/bgfx/shader.cpp create mode 100644 src/renderer/bgfx/shader.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 16f6ec373..8e6d4cadb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1219,11 +1219,13 @@ if (NOT DEFINED IMPACTO_DISABLE_BGFX) list(APPEND Impacto_Src src/renderer/bgfx/framebuffer.cpp src/renderer/bgfx/renderer.cpp + src/renderer/bgfx/shader.cpp src/renderer/bgfx/window.cpp ) list(APPEND Impacto_Header src/renderer/bgfx/framebuffer.h src/renderer/bgfx/renderer.h + src/renderer/bgfx/shader.h src/renderer/bgfx/window.h ) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 74b47b063..b4a7295f2 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -133,6 +133,9 @@ Renderer::Renderer() { throw std::runtime_error(errorMsg); } + ShaderPrograms[ShaderProgramType::Sprite] = + ShaderProgram::Create("vs_sprite", "fs_sprite"); + ImGui_Implbgfx_Init(IMGUI_VIEW); switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 549237e0c..762ce864c 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -3,6 +3,9 @@ #include "../renderer.h" #include "framebuffer.h" +#include "shader.h" + +#include namespace Impacto::Bgfx { @@ -140,6 +143,9 @@ class Renderer final : public BaseRenderer { glm::mat4 ViewMatrix; glm::mat4 ProjectionMatrix; glm::mat4 BackBufferProjectionMatrix; + + magic_enum::containers::array> + ShaderPrograms; }; } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shader.cpp b/src/renderer/bgfx/shader.cpp new file mode 100644 index 000000000..bd1115829 --- /dev/null +++ b/src/renderer/bgfx/shader.cpp @@ -0,0 +1,120 @@ +#include "shader.h" + +#include + +#include "../../log.h" + +namespace Impacto::Bgfx { + +ShaderProgram::ShaderProgram(ShaderProgram&& other) { + *this = std::move(other); +} + +ShaderProgram& ShaderProgram::operator=(ShaderProgram&& other) { + if (&other == this) return *this; + Reset(true); + if (!other.IsInit) return *this; + + IsInit = true; + ProgramHandle = other.ProgramHandle; + VertexShader = other.VertexShader; + FragmentShader = other.FragmentShader; + + other.Reset(false); + + return *this; +} + +ShaderProgram::~ShaderProgram() { Reset(true); } + +std::optional ShaderProgram::Create( + const std::string_view vertexShaderName, + const std::string_view fragmentShaderName) { + const std::string_view pathPrefix = []() -> std::string_view { + switch (bgfx::getRendererType()) { + using enum bgfx::RendererType::Enum; + case Direct3D11: + case Direct3D12: + return "dx11"; + case Metal: + return "metal"; + case OpenGLES: + return "essl"; + case OpenGL: + return "glsl"; + case Vulkan: + return "spirv"; + + case Noop: + case Agc: + case Gnm: + case Nvn: + case Count: + break; + } + return ""; + }(); + if (pathPrefix.empty()) { + const std::string errorMsg = + fmt::format("Unsupported renderer type for shaders: \"{:s}\"\n", + magic_enum::enum_name(bgfx::getRendererType())); + ImpLog(LogLevel::Fatal, LogChannel::Render, "{:s}\n", errorMsg); + throw errorMsg; + } + + const std::string vertexShaderPath = fmt::format( + "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, vertexShaderName); + const std::optional vertexShader = + CreateShader(vertexShaderPath.c_str()); + if (!vertexShader.has_value()) return std::nullopt; + + const std::string fragmentShaderPath = fmt::format( + "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, fragmentShaderName); + const std::optional fragmentShader = + CreateShader(fragmentShaderPath.c_str()); + if (!fragmentShader.has_value()) return std::nullopt; + + ShaderProgram program; + + program.VertexShader = *vertexShader; + program.FragmentShader = *fragmentShader; + + program.ProgramHandle = + bgfx::createProgram(program.VertexShader, program.FragmentShader, true); + assert(bgfx::isValid(program.ProgramHandle)); + + program.IsInit = true; + + return program; +} + +std::optional ShaderProgram::CreateShader( + const char* const sourcePath) { + size_t fileSize; + void* const source = SDL_LoadFile(sourcePath, &fileSize); + if (source == nullptr) { + ImpLog(LogLevel::Error, LogChannel::Render, + "Failed to read shader source file \"{:s}\": {:s}\n", sourcePath, + SDL_GetError()); + return std::nullopt; + } + + bgfx::ShaderHandle shader = + bgfx::createShader(bgfx::copy(source, static_cast(fileSize))); + assert(bgfx::isValid(shader)); + + SDL_free(source); + + return shader; +} + +void ShaderProgram::Reset(bool cleanUpResources) { + if (!IsInit) return; + IsInit = false; + + if (cleanUpResources) { + bgfx::destroy(ProgramHandle); + } +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h new file mode 100644 index 000000000..bb468dbd8 --- /dev/null +++ b/src/renderer/bgfx/shader.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include +#include +#include + +namespace Impacto::Bgfx { + +class ShaderProgram { + public: + ShaderProgram(const ShaderProgram&) = delete; + ShaderProgram(ShaderProgram&&); + ~ShaderProgram(); + + ShaderProgram& operator=(const ShaderProgram&) = delete; + ShaderProgram& operator=(ShaderProgram&&); + + [[nodiscard]] static std::optional Create( + const std::string_view vertexShaderName, + const std::string_view fragmentShaderName); + + operator bgfx::ProgramHandle() { return GetProgramHandle(); } + + [[nodiscard]] bgfx::ProgramHandle GetProgramHandle() { + assert(IsInit && bgfx::isValid(ProgramHandle)); + return ProgramHandle; + } + + private: + ShaderProgram() = default; + + bool IsInit = false; + + bgfx::ProgramHandle ProgramHandle; + + bgfx::ShaderHandle VertexShader; + bgfx::ShaderHandle FragmentShader; + + void Reset(bool cleanUpResources); + + [[nodiscard]] static std::optional CreateShader( + const char* sourcePath); +}; + +} // namespace Impacto::Bgfx From d8e16c1dd5ab8a4cd4cde43f265f108b38c01254 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sat, 5 Sep 2026 22:05:18 +0200 Subject: [PATCH 08/60] Implement shader uniform management --- CMakeLists.txt | 6 +- src/renderer/bgfx/renderer.cpp | 6 +- src/renderer/bgfx/renderer.h | 3 +- src/renderer/bgfx/shader.cpp | 120 ----------------------- src/renderer/bgfx/shader.h | 137 ++++++++++++++++++++++++-- src/renderer/bgfx/shaders/sprite.h | 17 ++++ src/renderer/bgfx/uniform.h | 152 +++++++++++++++++++++++++++++ vcpkg.json | 1 + 8 files changed, 308 insertions(+), 134 deletions(-) delete mode 100644 src/renderer/bgfx/shader.cpp create mode 100644 src/renderer/bgfx/shaders/sprite.h create mode 100644 src/renderer/bgfx/uniform.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e6d4cadb..d65fcf3ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1042,7 +1042,7 @@ list(APPEND Impacto_Include_Dirs ${WebP_INCLUDE_DIRS}) find_package(fmt CONFIG REQUIRED) find_package(glm CONFIG REQUIRED) -find_package(Boost REQUIRED COMPONENTS circular_buffer) +find_package(Boost REQUIRED COMPONENTS circular_buffer pfr) find_package(pugixml CONFIG REQUIRED) find_package(unordered_dense CONFIG REQUIRED) find_package(readerwriterqueue CONFIG REQUIRED) @@ -1063,6 +1063,7 @@ list(APPEND Impacto_Libs concurrentqueue::concurrentqueue readerwriterqueue::readerwriterqueue Boost::circular_buffer + Boost::pfr toml11::toml11 Freetype::Freetype harfbuzz::harfbuzz @@ -1219,7 +1220,6 @@ if (NOT DEFINED IMPACTO_DISABLE_BGFX) list(APPEND Impacto_Src src/renderer/bgfx/framebuffer.cpp src/renderer/bgfx/renderer.cpp - src/renderer/bgfx/shader.cpp src/renderer/bgfx/window.cpp ) list(APPEND Impacto_Header @@ -1227,6 +1227,8 @@ if (NOT DEFINED IMPACTO_DISABLE_BGFX) src/renderer/bgfx/renderer.h src/renderer/bgfx/shader.h src/renderer/bgfx/window.h + + src/renderer/bgfx/shaders/sprite.h ) set(Bgfx_Vertex_Shaders diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index b4a7295f2..37ac5c0be 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -133,8 +133,10 @@ Renderer::Renderer() { throw std::runtime_error(errorMsg); } - ShaderPrograms[ShaderProgramType::Sprite] = - ShaderProgram::Create("vs_sprite", "fs_sprite"); + { + using enum ShaderProgramType; + SpriteShader = ShaderProgram::Create("vs_sprite", "fs_sprite"); + } ImGui_Implbgfx_Init(IMGUI_VIEW); switch (UserConfig::AdvancedSettings.ActiveRenderer) { diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 762ce864c..9c155df7b 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -144,8 +144,7 @@ class Renderer final : public BaseRenderer { glm::mat4 ProjectionMatrix; glm::mat4 BackBufferProjectionMatrix; - magic_enum::containers::array> - ShaderPrograms; + std::optional> SpriteShader; }; } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shader.cpp b/src/renderer/bgfx/shader.cpp deleted file mode 100644 index bd1115829..000000000 --- a/src/renderer/bgfx/shader.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "shader.h" - -#include - -#include "../../log.h" - -namespace Impacto::Bgfx { - -ShaderProgram::ShaderProgram(ShaderProgram&& other) { - *this = std::move(other); -} - -ShaderProgram& ShaderProgram::operator=(ShaderProgram&& other) { - if (&other == this) return *this; - Reset(true); - if (!other.IsInit) return *this; - - IsInit = true; - ProgramHandle = other.ProgramHandle; - VertexShader = other.VertexShader; - FragmentShader = other.FragmentShader; - - other.Reset(false); - - return *this; -} - -ShaderProgram::~ShaderProgram() { Reset(true); } - -std::optional ShaderProgram::Create( - const std::string_view vertexShaderName, - const std::string_view fragmentShaderName) { - const std::string_view pathPrefix = []() -> std::string_view { - switch (bgfx::getRendererType()) { - using enum bgfx::RendererType::Enum; - case Direct3D11: - case Direct3D12: - return "dx11"; - case Metal: - return "metal"; - case OpenGLES: - return "essl"; - case OpenGL: - return "glsl"; - case Vulkan: - return "spirv"; - - case Noop: - case Agc: - case Gnm: - case Nvn: - case Count: - break; - } - return ""; - }(); - if (pathPrefix.empty()) { - const std::string errorMsg = - fmt::format("Unsupported renderer type for shaders: \"{:s}\"\n", - magic_enum::enum_name(bgfx::getRendererType())); - ImpLog(LogLevel::Fatal, LogChannel::Render, "{:s}\n", errorMsg); - throw errorMsg; - } - - const std::string vertexShaderPath = fmt::format( - "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, vertexShaderName); - const std::optional vertexShader = - CreateShader(vertexShaderPath.c_str()); - if (!vertexShader.has_value()) return std::nullopt; - - const std::string fragmentShaderPath = fmt::format( - "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, fragmentShaderName); - const std::optional fragmentShader = - CreateShader(fragmentShaderPath.c_str()); - if (!fragmentShader.has_value()) return std::nullopt; - - ShaderProgram program; - - program.VertexShader = *vertexShader; - program.FragmentShader = *fragmentShader; - - program.ProgramHandle = - bgfx::createProgram(program.VertexShader, program.FragmentShader, true); - assert(bgfx::isValid(program.ProgramHandle)); - - program.IsInit = true; - - return program; -} - -std::optional ShaderProgram::CreateShader( - const char* const sourcePath) { - size_t fileSize; - void* const source = SDL_LoadFile(sourcePath, &fileSize); - if (source == nullptr) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to read shader source file \"{:s}\": {:s}\n", sourcePath, - SDL_GetError()); - return std::nullopt; - } - - bgfx::ShaderHandle shader = - bgfx::createShader(bgfx::copy(source, static_cast(fileSize))); - assert(bgfx::isValid(shader)); - - SDL_free(source); - - return shader; -} - -void ShaderProgram::Reset(bool cleanUpResources) { - if (!IsInit) return; - IsInit = false; - - if (cleanUpResources) { - bgfx::destroy(ProgramHandle); - } -} - -} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h index bb468dbd8..a2cf77441 100644 --- a/src/renderer/bgfx/shader.h +++ b/src/renderer/bgfx/shader.h @@ -1,23 +1,30 @@ #pragma once #include +#include +#include #include #include #include +#include "../../log.h" + +#include "shaders/sprite.h" + namespace Impacto::Bgfx { +template class ShaderProgram { public: - ShaderProgram(const ShaderProgram&) = delete; - ShaderProgram(ShaderProgram&&); - ~ShaderProgram(); + ShaderProgram(const ShaderProgram&) = delete; + ShaderProgram(ShaderProgram&& other) { *this = std::move(other); } + ~ShaderProgram() { Reset(true); } - ShaderProgram& operator=(const ShaderProgram&) = delete; - ShaderProgram& operator=(ShaderProgram&&); + ShaderProgram& operator=(const ShaderProgram&) = delete; + ShaderProgram& operator=(ShaderProgram&&); - [[nodiscard]] static std::optional Create( + [[nodiscard]] static std::optional> Create( const std::string_view vertexShaderName, const std::string_view fragmentShaderName); @@ -28,6 +35,10 @@ class ShaderProgram { return ProgramHandle; } + void SubmitUniforms(const Uniforms& newUniforms) { + ShaderUniformsState->Submit(newUniforms); + } + private: ShaderProgram() = default; @@ -40,8 +51,118 @@ class ShaderProgram { void Reset(bool cleanUpResources); - [[nodiscard]] static std::optional CreateShader( - const char* sourcePath); + std::optional> ShaderUniformsState; }; +template +ShaderProgram& ShaderProgram::operator=( + ShaderProgram&& other) { + if (&other == this) return *this; + Reset(true); + if (!other.IsInit) return *this; + + IsInit = true; + ProgramHandle = other.ProgramHandle; + VertexShader = other.VertexShader; + FragmentShader = other.FragmentShader; + + other.Reset(false); + + return *this; +} + +[[nodiscard]] static inline std::optional CreateShader( + const char* const sourcePath) { + size_t fileSize; + void* const source = SDL_LoadFile(sourcePath, &fileSize); + if (source == nullptr) { + ImpLog(LogLevel::Error, LogChannel::Render, + "Failed to read shader source file \"{:s}\": {:s}\n", sourcePath, + SDL_GetError()); + return std::nullopt; + } + + bgfx::ShaderHandle shader = + bgfx::createShader(bgfx::copy(source, static_cast(fileSize))); + assert(bgfx::isValid(shader)); + + SDL_free(source); + + return shader; +} + +template +std::optional> ShaderProgram::Create( + const std::string_view vertexShaderName, + const std::string_view fragmentShaderName) { + const std::string_view pathPrefix = []() -> std::string_view { + switch (bgfx::getRendererType()) { + using enum bgfx::RendererType::Enum; + case Direct3D11: + case Direct3D12: + return "dx11"; + case Metal: + return "metal"; + case OpenGLES: + return "essl"; + case OpenGL: + return "glsl"; + case Vulkan: + return "spirv"; + + case Noop: + case Agc: + case Gnm: + case Nvn: + case Count: + break; + } + return ""; + }(); + if (pathPrefix.empty()) { + const std::string errorMsg = + fmt::format("Unsupported renderer type for shaders: \"{:s}\"\n", + magic_enum::enum_name(bgfx::getRendererType())); + ImpLog(LogLevel::Fatal, LogChannel::Render, "{:s}\n", errorMsg); + throw errorMsg; + } + + const std::string vertexShaderPath = fmt::format( + "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, vertexShaderName); + const std::optional vertexShader = + CreateShader(vertexShaderPath.c_str()); + if (!vertexShader.has_value()) return std::nullopt; + + const std::string fragmentShaderPath = fmt::format( + "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, fragmentShaderName); + const std::optional fragmentShader = + CreateShader(fragmentShaderPath.c_str()); + if (!fragmentShader.has_value()) return std::nullopt; + + ShaderProgram program; + + program.VertexShader = *vertexShader; + program.FragmentShader = *fragmentShader; + + program.ProgramHandle = + bgfx::createProgram(program.VertexShader, program.FragmentShader, true); + assert(bgfx::isValid(program.ProgramHandle)); + + program.ShaderUniformsState.emplace(program.ProgramHandle); + + program.IsInit = true; + + return program; +} + +template +void ShaderProgram::Reset(bool cleanUpResources) { + if (!IsInit) return; + IsInit = false; + + if (cleanUpResources) { + bgfx::destroy(ProgramHandle); + } +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shaders/sprite.h b/src/renderer/bgfx/shaders/sprite.h new file mode 100644 index 000000000..7ad10e00b --- /dev/null +++ b/src/renderer/bgfx/shaders/sprite.h @@ -0,0 +1,17 @@ +#pragma once + +#include "../uniform.h" + +namespace Impacto::Bgfx { + +template <> +struct Uniforms { + glm::vec3 ColorShift = glm::vec3(0.0f); +}; + +template <> +struct UniformHandles { + DECLARE_UNIFORM_HANDLE(Sprite, ColorShift, u_colorShift, 1); +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h new file mode 100644 index 000000000..12de988c8 --- /dev/null +++ b/src/renderer/bgfx/uniform.h @@ -0,0 +1,152 @@ +#pragma once + +#include +#include + +#include "../renderer.h" + +namespace Impacto::Bgfx { + +template +struct Uniforms; + +template +struct UniformHandles; + +template +class UniformsState { + public: + UniformsState() = delete; + UniformsState(bgfx::ProgramHandle program) : Program(program) { + Submit(Uniforms{}); + } + + void Submit(const Uniforms& newUniforms); + + private: + std::optional> CurrentUniforms; + UniformHandles Handles; + + bgfx::ProgramHandle Program; +}; + +struct UniformHandle { + public: + UniformHandle() = delete; + UniformHandle(const UniformHandle&) = delete; + UniformHandle(UniformHandle&& other) { *this = std::move(other); } + ~UniformHandle() { Reset(); } + + UniformHandle& operator=(const UniformHandle&) = delete; + UniformHandle& operator=(UniformHandle&& other) { + if (this == &other) return *this; + Reset(); + if (!other.Handle.has_value()) return *this; + + Handle = other.Handle; + other.Handle.reset(); + + return *this; + } + + UniformHandle(const char* name, bgfx::UniformType::Enum type, + uint16_t num = 1) + : Handle(bgfx::createUniform(name, type, num)) { + assert(bgfx::isValid(*Handle)); + } + + bgfx::UniformHandle GetHandle() { + assert(bgfx::isValid(*Handle)); + return *Handle; + } + operator bgfx::UniformHandle() { return GetHandle(); } + + private: + std::optional Handle; + + void Reset() { + if (!Handle.has_value()) return; + + bgfx::destroy(*Handle); + Handle.reset(); + } +}; + +template +void UniformsState::Submit(const Uniforms& newUniforms) { + constexpr static auto uniformNames = + boost::pfr::names_as_array>(); + constexpr static auto handleNames = + boost::pfr::names_as_array>(); + static_assert(uniformNames.size() == handleNames.size()); + + const auto updateUniform = [&] { + constexpr auto handleIt = + std::ranges::find(handleNames, uniformNames[UniformIdx]); + static_assert(handleIt != handleNames.end() && + "Uniform and UniformHandles struct need to share the same " + "member names"); + constexpr size_t handleIdx = std::distance(handleNames.begin(), handleIt); + + if (!CurrentUniforms.has_value() || + boost::pfr::get(*CurrentUniforms) != + boost::pfr::get(newUniforms)) { + SetUniform(boost::pfr::get(Handles), + boost::pfr::get(newUniforms)); + } + }; + + [&](std::index_sequence) { + (updateUniform.template operator()(), ...); + }(std::make_index_sequence{}); + + CurrentUniforms = newUniforms; +} + +template +constexpr bgfx::UniformType::Enum GetUniformType(); + +template + requires requires(T vec) { + { glm::vec{vec} } -> std::same_as; + } +constexpr bgfx::UniformType::Enum GetUniformType() { + return bgfx::UniformType::Vec4; +} + +template +void SetUniform(bgfx::UniformHandle handle, const T& value); + +template <> +inline void SetUniform(bgfx::UniformHandle handle, const glm::vec4& value) { + static_assert(GetUniformType>() == + bgfx::UniformType::Vec4); + + bgfx::setUniform(handle, glm::value_ptr(value), 1); +} + +template + requires(requires(T vec) { + { glm::vec{vec} } -> std::same_as; + } && !std::is_same_v) +inline void SetUniform(bgfx::UniformHandle handle, const T& value) { + static_assert(GetUniformType>() == bgfx::UniformType::Vec4); + + const glm::vec4 vec4(value, glm::vec<4 - T::length(), float>(0.0f)); + bgfx::setUniform(handle, glm::value_ptr(vec4), 1); +} + +template <> +inline void SetUniform(bgfx::UniformHandle handle, const float& value) { + SetUniform(handle, glm::vec1(value)); +} + +#define DECLARE_UNIFORM_HANDLE(shaderProgramType, memberName, uniformName, \ + num) \ + UniformHandle memberName = UniformHandle( \ + #uniformName, \ + GetUniformType:: \ + memberName)>(), \ + num) + +} // namespace Impacto::Bgfx diff --git a/vcpkg.json b/vcpkg.json index af3269bbd..c02838348 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -50,6 +50,7 @@ "readerwriterqueue", "unordered-dense", "boost-circular-buffer", + "boost-pfr", "toml11", "freetype", "harfbuzz", From c145cc0f262aa0124abfb7e3448b70389860f35b Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 6 Sep 2026 18:25:20 +0200 Subject: [PATCH 09/60] Include compiled bgfx shaders as headers --- CMakeLists.txt | 57 ++++++++--- src/renderer/bgfx/renderer.cpp | 4 +- src/renderer/bgfx/shader.h | 99 ++++---------------- src/renderer/bgfx/shaders/shaders.h.in | 50 ++++++++++ src/shaders/bgfx/{source => }/fs_sprite.sc | 0 src/shaders/bgfx/{source => }/varying.def.sc | 0 src/shaders/bgfx/{source => }/vs_sprite.sc | 0 7 files changed, 113 insertions(+), 97 deletions(-) create mode 100644 src/renderer/bgfx/shaders/shaders.h.in rename src/shaders/bgfx/{source => }/fs_sprite.sc (100%) rename src/shaders/bgfx/{source => }/varying.def.sc (100%) rename src/shaders/bgfx/{source => }/vs_sprite.sc (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d65fcf3ad..60a874a75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1232,26 +1232,55 @@ if (NOT DEFINED IMPACTO_DISABLE_BGFX) ) set(Bgfx_Vertex_Shaders - src/shaders/bgfx/source/vs_sprite.sc + src/shaders/bgfx/vs_sprite.sc ) set(Bgfx_Fragment_Shaders - src/shaders/bgfx/source/fs_sprite.sc + src/shaders/bgfx/fs_sprite.sc ) + set(Bgfx_Shaders ${Bgfx_Vertex_Shaders} ${Bgfx_Fragment_Shaders}) + bgfx_compile_shaders( TYPE VERTEX SHADERS ${Bgfx_Vertex_Shaders} - VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/bgfx/source/varying.def.sc - OUTPUT_DIR src/shaders/bgfx + VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/bgfx/varying.def.sc + OUTPUT_DIR "include/bgfx/shaders" + AS_HEADERS ) bgfx_compile_shaders( TYPE FRAGMENT SHADERS ${Bgfx_Fragment_Shaders} - VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/bgfx/source/varying.def.sc - OUTPUT_DIR src/shaders/bgfx + VARYING_DEF ${CMAKE_SOURCE_DIR}/src/shaders/bgfx/varying.def.sc + OUTPUT_DIR "include/bgfx/shaders" + AS_HEADERS ) - list(APPEND Impacto_Src ${Bgfx_Vertex_Shaders} ${Bgfx_Fragment_Shaders}) + add_library(bgfx_shaders INTERFACE ${Bgfx_Shaders}) + list(APPEND Impacto_Lib_Targets bgfx_shaders) + + # Automatically stamp out headers for including the shader source code. + # + # * /include/bgfx/shaders/ includes header files for each shader, + # containing the compiled shader binaries in an array. + # + # * /include/bgfx/shaders/.sc.h conditionally includes these compiled + # shader binaries based on which rendering backends are enabled, and stores them + # in an array of spans for easier access. + # These files are based on the /src/renderer/bgfx/shaders/shaders.h.in template file. + # + # * /include/bgfx/shader_contents.h includes all shader headers and should be included + # in the renderer implementation to access the shader source code. + set(shader_content_header "#pragma once\n") + foreach (shader IN LISTS Bgfx_Shaders) + string(REGEX MATCH "[^\\/]*$" SHADER_NAME ${shader}) + string(REGEX MATCH "^[^\.]*" SHADER_BASE_NAME ${SHADER_NAME}) + configure_file( + src/renderer/bgfx/shaders/shaders.h.in + "${CMAKE_BINARY_DIR}/include/bgfx/shaders/${SHADER_NAME}.h" + ) + string(APPEND shader_content_header "#include \"shaders/${SHADER_NAME}.h\"\n") + endforeach() + file(WRITE ${CMAKE_BINARY_DIR}/include/bgfx/shader_content.h ${shader_content_header}) endif() if (NOT DEFINED IMPACTO_DISABLE_FFMPEG) @@ -1343,7 +1372,7 @@ list(APPEND Impacto_Libs ${Impacto_Lib_Targets}) target_link_libraries(impacto PRIVATE ${Impacto_Libs}) target_compile_options(impacto PRIVATE "$<$:/utf-8>") -target_compile_options(impacto PRIVATE "$<$:/utf-8>") +target_compile_options(impacto PRIVATE "$<$:/utf-8;/Zc:__cplusplus>") if (IMPACTO_WARNINGS) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") @@ -1466,9 +1495,9 @@ elseif(APPLE) RESOURCE DESTINATION . ) install( - DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/shaders" "${PROJECT_BINARY_DIR}/src/shaders" + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/shaders" DESTINATION "Impacto.app/Contents/Resources/" - PATTERN "bgfx/source" EXCLUDE + PATTERN "bgfx" EXCLUDE ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/resources" DESTINATION "Impacto.app/Contents/Resources/" @@ -1501,9 +1530,9 @@ endif () if (NOT ANDROID) if(NOT APPLE) install( - DIRECTORY src/shaders ${PROJECT_BINARY_DIR}/src/shaders + DIRECTORY src/shaders DESTINATION . - PATTERN "bgfx/source" EXCLUDE + PATTERN "bgfx" EXCLUDE ) install(DIRECTORY resources DESTINATION .) endif() @@ -1517,9 +1546,9 @@ if (NOT ANDROID) endif() else() install( - DIRECTORY src/shaders ${PROJECT_BINARY_DIR}/src/shaders + DIRECTORY src/shaders DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets - PATTERN "bgfx/source" EXCLUDE + PATTERN "bgfx" EXCLUDE ) install(DIRECTORY profiles DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets) install(DIRECTORY resources DESTINATION ${CMAKE_SOURCE_DIR}/android/app/src/main/assets PATTERN "*/gamedata/*" EXCLUDE) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 37ac5c0be..02ef9532f 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -3,6 +3,8 @@ #include "../../log.h" #include "../../userconfig.h" +#include + #include #include #include @@ -135,7 +137,7 @@ Renderer::Renderer() { { using enum ShaderProgramType; - SpriteShader = ShaderProgram::Create("vs_sprite", "fs_sprite"); + SpriteShader.emplace(vs_sprite_shader, fs_sprite_shader); } ImGui_Implbgfx_Init(IMGUI_VIEW); diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h index a2cf77441..caf24b51b 100644 --- a/src/renderer/bgfx/shader.h +++ b/src/renderer/bgfx/shader.h @@ -1,8 +1,10 @@ #pragma once #include +#include #include #include +#include #include #include @@ -17,6 +19,7 @@ namespace Impacto::Bgfx { template class ShaderProgram { public: + ShaderProgram() = delete; ShaderProgram(const ShaderProgram&) = delete; ShaderProgram(ShaderProgram&& other) { *this = std::move(other); } ~ShaderProgram() { Reset(true); } @@ -24,9 +27,8 @@ class ShaderProgram { ShaderProgram& operator=(const ShaderProgram&) = delete; ShaderProgram& operator=(ShaderProgram&&); - [[nodiscard]] static std::optional> Create( - const std::string_view vertexShaderName, - const std::string_view fragmentShaderName); + ShaderProgram(const bgfx::EmbeddedShader& vertexShader, + const bgfx::EmbeddedShader& fragmentShader); operator bgfx::ProgramHandle() { return GetProgramHandle(); } @@ -40,8 +42,6 @@ class ShaderProgram { } private: - ShaderProgram() = default; - bool IsInit = false; bgfx::ProgramHandle ProgramHandle; @@ -71,88 +71,23 @@ ShaderProgram& ShaderProgram::operator=( return *this; } -[[nodiscard]] static inline std::optional CreateShader( - const char* const sourcePath) { - size_t fileSize; - void* const source = SDL_LoadFile(sourcePath, &fileSize); - if (source == nullptr) { - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to read shader source file \"{:s}\": {:s}\n", sourcePath, - SDL_GetError()); - return std::nullopt; - } - - bgfx::ShaderHandle shader = - bgfx::createShader(bgfx::copy(source, static_cast(fileSize))); - assert(bgfx::isValid(shader)); - - SDL_free(source); - - return shader; -} - template -std::optional> ShaderProgram::Create( - const std::string_view vertexShaderName, - const std::string_view fragmentShaderName) { - const std::string_view pathPrefix = []() -> std::string_view { - switch (bgfx::getRendererType()) { - using enum bgfx::RendererType::Enum; - case Direct3D11: - case Direct3D12: - return "dx11"; - case Metal: - return "metal"; - case OpenGLES: - return "essl"; - case OpenGL: - return "glsl"; - case Vulkan: - return "spirv"; - - case Noop: - case Agc: - case Gnm: - case Nvn: - case Count: - break; - } - return ""; - }(); - if (pathPrefix.empty()) { - const std::string errorMsg = - fmt::format("Unsupported renderer type for shaders: \"{:s}\"\n", - magic_enum::enum_name(bgfx::getRendererType())); - ImpLog(LogLevel::Fatal, LogChannel::Render, "{:s}\n", errorMsg); - throw errorMsg; - } - - const std::string vertexShaderPath = fmt::format( - "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, vertexShaderName); - const std::optional vertexShader = - CreateShader(vertexShaderPath.c_str()); - if (!vertexShader.has_value()) return std::nullopt; - - const std::string fragmentShaderPath = fmt::format( - "./shaders/bgfx/{:s}/{:s}.sc.bin", pathPrefix, fragmentShaderName); - const std::optional fragmentShader = - CreateShader(fragmentShaderPath.c_str()); - if (!fragmentShader.has_value()) return std::nullopt; +ShaderProgram::ShaderProgram(const bgfx::EmbeddedShader& vertexShader, + const bgfx::EmbeddedShader& fragmentShader) { + VertexShader = bgfx::createEmbeddedShader( + &vertexShader, bgfx::getRendererType(), vertexShader.name); + assert(bgfx::isValid(VertexShader)); - ShaderProgram program; + FragmentShader = bgfx::createEmbeddedShader( + &fragmentShader, bgfx::getRendererType(), fragmentShader.name); + assert(bgfx::isValid(FragmentShader)); - program.VertexShader = *vertexShader; - program.FragmentShader = *fragmentShader; + ProgramHandle = bgfx::createProgram(VertexShader, FragmentShader, true); + assert(bgfx::isValid(ProgramHandle)); - program.ProgramHandle = - bgfx::createProgram(program.VertexShader, program.FragmentShader, true); - assert(bgfx::isValid(program.ProgramHandle)); + ShaderUniformsState.emplace(ProgramHandle); - program.ShaderUniformsState.emplace(program.ProgramHandle); - - program.IsInit = true; - - return program; + IsInit = true; } template diff --git a/src/renderer/bgfx/shaders/shaders.h.in b/src/renderer/bgfx/shaders/shaders.h.in new file mode 100644 index 000000000..867614e14 --- /dev/null +++ b/src/renderer/bgfx/shaders/shaders.h.in @@ -0,0 +1,50 @@ +#pragma once + +#include + +namespace Impacto::Bgfx { + +// clang-format off +#ifndef IMPACTO_DISABLE_OPENGL +#include "glsl/@SHADER_NAME@.bin.h" +#include "essl/@SHADER_NAME@.bin.h" +#endif + +#ifndef IMPACTO_DISABLE_DIRECT3D +#include "dx10/@SHADER_NAME@.bin.h" +#include "dx11/@SHADER_NAME@.bin.h" +#endif + +#ifndef IMPACTO_DISABLE_METAL +#include "metal/@SHADER_NAME@.bin.h" +#endif + +#ifndef IMPACTO_DISABLE_VULKAN +#include "spirv/@SHADER_NAME@.bin.h" +#endif + +const inline bgfx::EmbeddedShader @SHADER_BASE_NAME@_shader = { + "@SHADER_BASE_NAME@", + { +#ifndef IMPACTO_DISABLE_DIRECT3D + BGFX_EMBEDDED_SHADER_DXBC (bgfx::RendererType::Direct3D11, @SHADER_BASE_NAME@) + BGFX_EMBEDDED_SHADER_DXBC (bgfx::RendererType::Direct3D12, @SHADER_BASE_NAME@) +#endif +#ifndef IMPACTO_DISABLE_METAL + BGFX_EMBEDDED_SHADER_METAL(bgfx::RendererType::Metal, @SHADER_BASE_NAME@) +#endif +#ifndef IMPACTO_DISABLE_OPENGL + BGFX_EMBEDDED_SHADER_ESSL (bgfx::RendererType::OpenGLES, @SHADER_BASE_NAME@) + BGFX_EMBEDDED_SHADER_GLSL (bgfx::RendererType::OpenGL, @SHADER_BASE_NAME@) +#endif +#ifndef IMPACTO_DISABLE_VULKAN + BGFX_EMBEDDED_SHADER_SPIRV(bgfx::RendererType::Vulkan, @SHADER_BASE_NAME@) +#endif + { bgfx::RendererType::Noop, (const uint8_t*)"VSH\x5\x0\x0\x0\x0\x0\x0", 10 }, + { bgfx::RendererType::Count, NULL, 0 } + } +}; + +// clang-format on + +} // namespace Impacto::Bgfx diff --git a/src/shaders/bgfx/source/fs_sprite.sc b/src/shaders/bgfx/fs_sprite.sc similarity index 100% rename from src/shaders/bgfx/source/fs_sprite.sc rename to src/shaders/bgfx/fs_sprite.sc diff --git a/src/shaders/bgfx/source/varying.def.sc b/src/shaders/bgfx/varying.def.sc similarity index 100% rename from src/shaders/bgfx/source/varying.def.sc rename to src/shaders/bgfx/varying.def.sc diff --git a/src/shaders/bgfx/source/vs_sprite.sc b/src/shaders/bgfx/vs_sprite.sc similarity index 100% rename from src/shaders/bgfx/source/vs_sprite.sc rename to src/shaders/bgfx/vs_sprite.sc From 03d75e50c242fff276f52567c9e295fafe936dd0 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Mon, 7 Sep 2026 15:31:42 +0200 Subject: [PATCH 10/60] Add renderer backend selection to overlay --- src/overlay.cpp | 25 +++++++++++++++++++++++++ src/userconfig.h | 13 ++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index 09586cb3a..31b4b6920 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -420,6 +420,31 @@ static void ShowGamePicker(std::string& selectedGame) { dispModeRadio("Fullscreen", DisplayMode::Fullscreen); ImGui::SameLine(); dispModeRadio("Borderless", DisplayMode::Borderless); + + ImGui::AlignTextToFramePadding(); + ImGui::Text("Renderer Backend"); + if (Profile::Game::HasInit) { + ImGui::SameLine(); + ImGui::Text("(Will apply on next launch)"); + } + ImGui::SameLine(); + ImGui::SetNextItemWidth(comboWidth); + auto& activeRenderer = UserConfig::AdvancedSettings.ActiveRenderer; + if (ImGui::BeginCombo("##ChooseRenderer", + magic_enum::enum_name(activeRenderer).data())) { + constexpr static auto rendererBackends = + magic_enum::enum_entries(); + for (const auto& [type, name] : rendererBackends) { + bool isSelected = activeRenderer == type; + if (ImGui::Selectable(name.data(), isSelected)) { + wasUpdated |= activeRenderer != type; + activeRenderer = type; + } + + if (isSelected) ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } } return wasUpdated; diff --git a/src/userconfig.h b/src/userconfig.h index fb570fc68..ea2c988d2 100644 --- a/src/userconfig.h +++ b/src/userconfig.h @@ -30,6 +30,17 @@ enum class RendererType : int { #endif }; +constexpr inline RendererType DefaultRendererType = +#if defined(SDL_PLATFORM_WIN32) + RendererType::Direct3D; +#elif defined(SDL_PLATFORM_MACOS) + RendererType::Metal; +#elif defined(SDL_PLATFORM_ANDROID) + RendererType::OpenGLES; +#else + RendererType::Vulkan; +#endif + enum class VideoPlayerType : int { None, FFmpeg, @@ -73,7 +84,7 @@ struct Config { bool SwapConfirmCancelButtons = false; }; struct AdvancedConfig { - RendererType ActiveRenderer = RendererType::OpenGL; + RendererType ActiveRenderer = DefaultRendererType; VideoPlayerType VideoPlayer = VideoPlayerType::FFmpeg; AudioBackendType ActiveAudioBackend = AudioBackendType::OpenAL; SubtitleAssBackendType SubtitleAssBackend = SubtitleAssBackendType::LibAss; From 24c9dd434fbb90880c4a083d3677814b761918e4 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 8 Sep 2026 15:55:00 +0200 Subject: [PATCH 11/60] Add Panic method and refine shutdown procedure --- src/audio/openal/audiobackend.cpp | 2 +- src/game.cpp | 11 ++++---- src/game.h | 2 +- src/games/cclcc/albummenu.cpp | 5 ++-- src/io/filemeta.cpp | 7 +++-- src/log.h | 18 +++++++++++++ src/main.cpp | 35 +++++++++---------------- src/profile/data/bgeff.cpp | 15 +++++------ src/profile/data/savesystem.cpp | 13 +++++---- src/profile/fonts.cpp | 12 ++++----- src/profile/gamedefinitions.cpp | 2 +- src/profile/profile.cpp | 34 +++++++++++------------- src/profile/profile_internal.cpp | 10 +++---- src/profile/profile_internal.h | 24 ++++++----------- src/profile/sprites.cpp | 4 +-- src/renderer/bgfx/renderer.cpp | 18 ++++--------- src/renderer/bgfx/renderer.h | 2 +- src/renderer/bgfx/window.cpp | 8 ++---- src/renderer/bgfx/window.h | 2 ++ src/renderer/opengl/3d/renderable3d.cpp | 6 ++--- src/renderer/opengl/renderer.cpp | 6 ++--- src/renderer/opengl/shader.cpp | 26 +++++------------- src/renderer/opengl/window.cpp | 18 ++++--------- src/renderer/opengl/window.h | 2 ++ src/renderer/renderer.cpp | 8 +++--- src/renderer/renderer.h | 4 +-- src/renderer/window.cpp | 16 +++++------ src/renderer/window.h | 2 ++ src/spritesheet.cpp | 5 +++- src/texture/texture.cpp | 2 +- src/vm/inst_system.cpp | 4 +-- src/vm/vm.cpp | 3 +-- 32 files changed, 139 insertions(+), 187 deletions(-) diff --git a/src/audio/openal/audiobackend.cpp b/src/audio/openal/audiobackend.cpp index 4fe38f06b..551bced86 100644 --- a/src/audio/openal/audiobackend.cpp +++ b/src/audio/openal/audiobackend.cpp @@ -25,7 +25,7 @@ void AL_APIENTRY DefaultDeviceChangedEventCallback( bool AudioBackend::Init() { AlcDevice = alcOpenDevice(NULL); if (!AlcDevice) { - ImpLog(LogLevel::Fatal, LogChannel::Audio, + ImpLog(LogLevel::Error, LogChannel::Audio, "Could not create OpenAL device\n"); return false; } diff --git a/src/game.cpp b/src/game.cpp index 508b7ec9c..bd2dd8b61 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -203,7 +203,7 @@ void InitGameProfile() { Profile::ClearProfile(); } -void Shutdown() { +void Shutdown(const int exitCode) { if (+Profile::Game::GameFeatures & +GameFeature::Audio) { Audio::AudioShutdown(); } @@ -212,11 +212,12 @@ void Shutdown() { Video::VideoShutdown(); } - if (+Profile::Game::GameFeatures & +GameFeature::Renderer2D) { - Renderer->Shutdown(); - } WorkQueue::StopWorkQueue(); - Window->Shutdown(); + + Renderer.reset(); + Window.reset(); + + exit(exitCode); } void LauncherUpdate(float dt) { diff --git a/src/game.h b/src/game.h index 52e12fbf1..fc5086b12 100644 --- a/src/game.h +++ b/src/game.h @@ -57,7 +57,7 @@ enum class DrawComponentType : uint8_t { void Init(); void InitGameProfile(); -void Shutdown(); +[[noreturn]] void Shutdown(int exitCode = EXIT_SUCCESS); void Update(float dt); void Render(); diff --git a/src/games/cclcc/albummenu.cpp b/src/games/cclcc/albummenu.cpp index 31f0f6d02..6a6a07ef3 100644 --- a/src/games/cclcc/albummenu.cpp +++ b/src/games/cclcc/albummenu.cpp @@ -84,9 +84,8 @@ void AlbumMenu::SetThumbnailDirections() { case FDIR_RIGHT: return RIGHT; } - ImpLog(LogLevel::Fatal, LogChannel::General, - "Invalid FocusDirection value: {}", static_cast(dir)); - exit(1); + Panic(LogChannel::General, "Invalid FocusDirection value: {}", + static_cast(dir)); }; for (auto& page : ThumbnailPages) { diff --git a/src/io/filemeta.cpp b/src/io/filemeta.cpp index b8e741a4a..f8753407a 100644 --- a/src/io/filemeta.cpp +++ b/src/io/filemeta.cpp @@ -70,10 +70,9 @@ std::string const& GetPlatformConfigDir() { #if defined(__ANDROID__) // prefer external storage dir for easier user access const char* configPath = SDL_GetAndroidExternalStoragePath(); if (!configPath) { - ImpLog(LogLevel::Fatal, LogChannel::IO, - "Failed to get Android external storage path, error: {}\n", - SDL_GetError()); - exit(1); + Panic(LogChannel::IO, + "Failed to get Android external storage path, error: {}\n", + SDL_GetError()); } return configPath; #elif defined(__unix__) // prefer .config over .local/share diff --git a/src/log.h b/src/log.h index d8d7d6e6a..89053ce04 100644 --- a/src/log.h +++ b/src/log.h @@ -2,6 +2,7 @@ #include "impacto.h" #include "util.h" +#include "game.h" #ifndef IMPACTO_DISABLE_OPENGL #include @@ -9,6 +10,8 @@ #include +#include + namespace Impacto { enum class LogLevel { Off = 0, @@ -103,6 +106,21 @@ void GLAPIENTRY LogGLMessageCallback(GLenum source, GLenum type, GLuint id, const void* userParam); #endif +#define Panic(logChannel, ...) \ + { \ + constexpr std::source_location _source_location = \ + std::source_location::current(); \ + Impacto::ImpLog(Impacto::LogLevel::Fatal, logChannel, \ + "Fatal error occurred at {:s}({:d}:{:d}) in {:s}", \ + _source_location.file_name(), _source_location.line(), \ + _source_location.column(), \ + _source_location.function_name()); \ + } \ + Impacto::ImpLog(Impacto::LogLevel::Fatal, \ + logChannel __VA_OPT__(, ) __VA_ARGS__); \ + assert(false); \ + Impacto::Game::Shutdown(EXIT_FAILURE) + } // namespace Impacto namespace magic_enum::customize { diff --git a/src/main.cpp b/src/main.cpp index 892aab180..25b7ee837 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,15 +62,11 @@ static void HandleArguments(std::vector args) { std::end(supportedArgs)) { if constexpr (std::invocable) { if (++i >= args.size()) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "Invalid number of arguments"); - exit(1); + Panic(LogChannel::General, "Invalid number of arguments"); } std::string_view input = args[i]; if (input[0] == '-') { - ImpLog(LogLevel::Fatal, LogChannel::General, - "Missing parameter for {}", arg); - exit(1); + Panic(LogChannel::General, "Missing parameter for {}", arg); } action(input); } else if constexpr (std::invocable) { @@ -100,12 +96,11 @@ static void HandleArguments(std::vector args) { std::optional logChannelOpt = StringToChannel(input); if (!logChannelOpt) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "Invalid log channel \"{}\", expected one of {}, All!\n", - input, - fmt::join(magic_enum::enum_names(), - ", ")); - exit(1); + Panic(LogChannel::General, + "Invalid log channel \"{}\", expected one of {}, All!\n", + input, + fmt::join(magic_enum::enum_names(), + ", ")); }; auto& logChannels = Impacto::UserConfig::CommonSettings.LogChannels; @@ -125,10 +120,9 @@ static void HandleArguments(std::vector args) { auto logLevelOpt = magic_enum::enum_cast(input); if (!logLevelOpt) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "Invalid log level \"{}\", expected one of {}!\n", input, - magic_enum::enum_names()); - exit(1); + Panic(LogChannel::General, + "Invalid log level \"{}\", expected one of {}!\n", input, + magic_enum::enum_names()); } Impacto::UserConfig::CommonSettings.LogLvl = *logLevelOpt; }, @@ -248,13 +242,10 @@ int main(int argc, char* argv[]) { Game::Shutdown(); #endif } catch (std::exception const& e) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "Fatal error occured: {}, exiting!\n", e.what()); - exit(1); + Panic(LogChannel::General, "Fatal error occurred: {}, exiting!\n", + e.what()); } catch (...) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "Unknown error occured, exiting!\n"); - exit(1); + Panic(LogChannel::General, "Unknown error occurred, exiting!\n"); } return 0; } diff --git a/src/profile/data/bgeff.cpp b/src/profile/data/bgeff.cpp index b347fb50e..4cfc755bd 100644 --- a/src/profile/data/bgeff.cpp +++ b/src/profile/data/bgeff.cpp @@ -32,10 +32,9 @@ void Load() { auto arraySize = lua_rawlen(LuaState, -1); if (arraySize != 5) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Expected five entries in shader definition defined; got {:d}\n", - arraySize); - Window->Shutdown(); + Panic(LogChannel::Profile, + "Expected five entries in shader definition defined; got {:d}\n", + arraySize); } Background2D::BgEffShaderMap.emplace( @@ -65,11 +64,9 @@ void Load() { auto arraySize = lua_rawlen(LuaState, -1); if (arraySize != 5) { - ImpLog( - LogLevel::Fatal, LogChannel::Profile, - "Expected five entries in texture id mapping defined; got {:d}\n", - arraySize); - Window->Shutdown(); + Panic(LogChannel::Profile, + "Expected five entries in texture id mapping defined; got {:d}\n", + arraySize); } Background2D::BgEffTextureIdMap.emplace( diff --git a/src/profile/data/savesystem.cpp b/src/profile/data/savesystem.cpp index afd6bf989..3d82aeb47 100644 --- a/src/profile/data/savesystem.cpp +++ b/src/profile/data/savesystem.cpp @@ -20,14 +20,14 @@ struct TryGetImpl { const std::optional bitFieldOffset = TryGetMember("BitFieldOffset"); if (!bitFieldOffset.has_value()) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, "Missing BitFieldOffset"); + ImpLog(LogLevel::Error, LogChannel::Profile, "Missing BitFieldOffset"); return std::nullopt; } const std::optional addedLinesPerScript = TryGetMember("AddedLinesPerScript"); if (!addedLinesPerScript.has_value()) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, + ImpLog(LogLevel::Error, LogChannel::Profile, "Missing AddedLinesPerScript"); return std::nullopt; } @@ -61,7 +61,7 @@ struct TryGetImpl { const std::optional scriptId = TryGetMember("ScriptId"); if (!scriptId.has_value()) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, + ImpLog(LogLevel::Error, LogChannel::Profile, "Missing ScriptId in equivalent line range"); return std::nullopt; } @@ -72,7 +72,7 @@ struct TryGetImpl { startLineId = TryGetMember("LineId"); if (!startLineId.has_value()) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, + ImpLog(LogLevel::Error, LogChannel::Profile, "Missing LineId in equivalent line range"); return std::nullopt; } @@ -82,7 +82,7 @@ struct TryGetImpl { endLineId = TryGetMember("EndLineId"); if (!endLineId.has_value()) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, + ImpLog(LogLevel::Error, LogChannel::Profile, "Missing EndLineId in equivalent line range"); return std::nullopt; } @@ -150,8 +150,7 @@ void Configure() { AssertIs(LUA_TTABLE); auto pairSize = lua_rawlen(LuaState, -1); if (pairSize != 2) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, "Expected two values\n"); - Window->Shutdown(); + Panic(LogChannel::Profile, "Expected two values\n"); } ScriptMessageData[i].LineCount = EnsureGetArrayElementByIndex(0); diff --git a/src/profile/fonts.cpp b/src/profile/fonts.cpp index c47bb642b..38e2f12bc 100644 --- a/src/profile/fonts.cpp +++ b/src/profile/fonts.cpp @@ -24,9 +24,8 @@ static std::vector EnsureGetAdvanceWidths(const std::string_view name, uint8_t* widthBin; int64_t widthSz; if (widthTablePath.Slurp((void*&)widthBin, widthSz) != IoError_OK) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Failed to load width table file for font {:s}\n", name); - Window->Shutdown(); + Panic(LogChannel::Profile, + "Failed to load width table file for font {:s}\n", name); } assert(widthSz % bytesPerGlyph == 0); @@ -179,10 +178,9 @@ void LoadFonts() { } break; case External: - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "External fonts cannot be loaded from the profile for {:s}\n", - name); - Window->Shutdown(); + Panic(LogChannel::Profile, + "External fonts cannot be loaded from the profile for {:s}\n", + name); break; } diff --git a/src/profile/gamedefinitions.cpp b/src/profile/gamedefinitions.cpp index a6637757f..8c5d513b9 100644 --- a/src/profile/gamedefinitions.cpp +++ b/src/profile/gamedefinitions.cpp @@ -18,7 +18,7 @@ struct TryGetImpl { TryGetMember("LauncherTheme").value_or(0xFFFFFF); if (!gameProfileOpt || gameProfileOpt->empty()) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, + ImpLog(LogLevel::Error, LogChannel::Profile, "Missing GameProfile path\n"); return std::nullopt; } diff --git a/src/profile/profile.cpp b/src/profile/profile.cpp index 3efad4ec7..83d92b3f9 100644 --- a/src/profile/profile.cpp +++ b/src/profile/profile.cpp @@ -42,16 +42,16 @@ static ankerl::unordered_dense::set> static void RunLuaScriptBuffer(std::span buffer) { if (luaL_loadbuffer(LuaState, buffer.data(), buffer.size(), buffer.data())) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Lua profile compile error: {:s}\n", lua_tostring(LuaState, -1)); + const std::string errorMsg = fmt::format( + "Lua profile compile error: {:s}\n", lua_tostring(LuaState, -1)); lua_close(LuaState); - exit(1); + Panic(LogChannel::Profile, "{:s}", errorMsg); } if (lua_pcall(LuaState, 0, 0, 0)) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Lua profile execute error: {:s}\n", lua_tostring(LuaState, -1)); + const std::string errorMsg = fmt::format( + "Lua profile execute error: {:s}\n", lua_tostring(LuaState, -1)); lua_close(LuaState); - exit(1); + Panic(LogChannel::Profile, "{:s}", errorMsg); } } @@ -59,9 +59,10 @@ static void RunLuaScript(const char* path) { ImpLog(LogLevel::Info, LogChannel::Profile, "Executing lua script {:s}\n", path); if (luaL_dofile(LuaState, path)) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Lua profile compile error: {:s}\n", lua_tostring(LuaState, -1)); - exit(1); + const std::string errorMsg = fmt::format( + "Lua profile compile error: {:s}\n", lua_tostring(LuaState, -1)); + lua_close(LuaState); + Panic(LogChannel::Profile, "{:s}", errorMsg); } ImpLog(LogLevel::Info, LogChannel::Profile, "Lua profile execute success\n"); } @@ -260,10 +261,7 @@ void Configure() { return; } - ImpLog(LogLevel::Fatal, LogChannel::Profile, "Failed to find {}.\n", - platformPath); - - throw std::runtime_error(fmt::format("Failed to find {}", fileName)); + Panic(LogChannel::Profile, "Failed to find {}.\n", platformPath); }; setupScriptPath("basepaths.lua", BasePathsPath); @@ -284,9 +282,8 @@ void Configure() { void ConfigureGameProfile() { auto activePatch = UserConfig::GetPatchProfile(); if (BasePaths::RootPatchesDir.empty() && activePatch) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Patch is enabled but no patch directory is specified\n"); - exit(1); + Panic(LogChannel::Profile, + "Patch is enabled but no patch directory is specified\n"); } auto const& activeGameDef = GameDefinitions.at(UserConfig::GetActiveGame()); @@ -295,12 +292,11 @@ void ConfigureGameProfile() { if (activePatch) { auto patchProfilePathItr = activeGameDef.Patch.find(*activePatch); if (patchProfilePathItr == activeGameDef.Patch.end()) { - ImpLog( - LogLevel::Fatal, LogChannel::Profile, + Panic( + LogChannel::Profile, "Patch is enabled but patch.lua path is missing for patch profile {} " "in game {} definition\n", *activePatch, UserConfig::GetActiveGame()); - exit(1); } RunLuaScript(patchProfilePathItr->second.c_str()); } diff --git a/src/profile/profile_internal.cpp b/src/profile/profile_internal.cpp index 0de074cfb..f4364adea 100644 --- a/src/profile/profile_internal.cpp +++ b/src/profile/profile_internal.cpp @@ -54,9 +54,7 @@ bool TryPushMember(char const* name) { void EnsurePushMember(char const* name) { bool success = TryPushMember(name); if (!success) { - std::string error = fmt::format("Expected member {:s}", name); - ImpLog(LogLevel::Fatal, LogChannel::Profile, "{:s}\n", error); - throw std::runtime_error(error); + Panic(LogChannel::Profile, "Expected member {:s}", name); } } @@ -68,10 +66,8 @@ void EnsurePushMemberOfType(char const* name, int type) { void AssertIs(int type) { int actualType = lua_type(LuaState, -1); if (actualType != type) { - std::string error = - fmt::format("Unexpected type {}, expected {}", actualType, type); - ImpLog(LogLevel::Fatal, LogChannel::Profile, "{:s}\n", error); - throw std::runtime_error(error); + Panic(LogChannel::Profile, "Unexpected type {}, expected {}", actualType, + type); } } diff --git a/src/profile/profile_internal.h b/src/profile/profile_internal.h index 10aaeecf7..da55d616d 100644 --- a/src/profile/profile_internal.h +++ b/src/profile/profile_internal.h @@ -155,9 +155,7 @@ inline T EnsureGet() { std::optional result = TryGet(); if (!result.has_value()) { - ImpLog(Impacto::LogLevel::Fatal, Impacto::LogChannel::Profile, - "Unexpected type\n"); - Impacto::Game::Shutdown(); + Panic(LogChannel::Profile, "Unexpected type\n"); } return result.value(); @@ -388,8 +386,7 @@ inline std::optional TryGet() { PushInitialIndex(); const auto errorHandler = [&](std::string error) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, "{:s}\n", error); - throw std::runtime_error(error); + Panic(LogChannel::Profile, "{:s}\n", error); }; T out; @@ -452,10 +449,8 @@ inline std::optional TryGet() { T result; ForEachProfileArray([&]([[maybe_unused]] size_t i) { if (i != result.size()) { - std::string error = fmt::format( - "Unexpected key {} in lua array, expected {}", i, result.size()); - ImpLog(LogLevel::Fatal, LogChannel::Profile, "{:s}\n", error); - throw std::runtime_error(error); + Panic(LogChannel::Profile, "Unexpected key {} in lua array, expected {}", + i, result.size()); } result.push_back(EnsureGet()); }); @@ -491,8 +486,7 @@ template inline std::optional TryGet() { if (!lua_istable(LuaState, -1)) return std::nullopt; auto errorHandler = [](std::string error) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, "{:s}\n", error); - throw std::runtime_error(error); + Panic(LogChannel::Profile, "{:s}\n", error); }; T result; @@ -567,11 +561,9 @@ template inline void GetArray(std::span out) { size_t actualCount = static_cast(lua_rawlen(LuaState, -1)); if (actualCount != out.size()) { - std::string error = - fmt::format("Expected to have {:d} values for array, got {:d}", - out.size(), actualCount); - ImpLog(LogLevel::Fatal, LogChannel::Profile, "{:s}\n", error); - throw std::runtime_error(error); + Panic(LogChannel::Profile, + "Expected to have {:d} values for array, got {:d}", out.size(), + actualCount); } ForEachProfileArray([&](uint32_t i) { out[i] = EnsureGetArrayElement(); }); diff --git a/src/profile/sprites.cpp b/src/profile/sprites.cpp index 97315d2f3..d813b0c9d 100644 --- a/src/profile/sprites.cpp +++ b/src/profile/sprites.cpp @@ -44,9 +44,7 @@ void LoadSpritesheets() { Io::Stream* stream; IoError err = sheet.Path.Open(&stream); if (err != IoError_OK) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Could not open spritesheet {:s}\n", name); - Window->Shutdown(); + Panic(LogChannel::Profile, "Could not open spritesheet {:s}\n", name); } futures.emplace_back(std::tuple( diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 02ef9532f..d50dfc352 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -71,10 +71,8 @@ Renderer::Renderer() { SDL_GetWindowProperties(Window->SDLWindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr); } else { - const std::string errorMsg = fmt::format( - "Unsupported video driver \"{:s}\"", SDL_GetCurrentVideoDriver()); - ImpLog(LogLevel::Fatal, LogChannel::Render, "{:s}", errorMsg); - throw std::runtime_error(errorMsg); + Panic(LogChannel::Render, "Unsupported video driver \"{:s}\"", + SDL_GetCurrentVideoDriver()); } #elif defined(SDL_PLATFORM_ANDROID) initStruct.platformData.nwh = @@ -95,9 +93,7 @@ Renderer::Renderer() { #endif if (!bgfx::init(initStruct)) { - constexpr const char* errorMsg = "Failed to initialize BGFX"; - ImpLog(LogLevel::Fatal, LogChannel::Render, errorMsg); - throw std::runtime_error(errorMsg); + Panic(LogChannel::Render, "Failed to initialize BGFX"); } BackBufferFrameBuffer = FrameBuffer::CreateBackBufferFrameBuffer(); @@ -111,9 +107,7 @@ Renderer::Renderer() { IndexBuffer = bgfx::createDynamicIndexBuffer( static_cast(Indices.size()), BGFX_BUFFER_ALLOW_RESIZE); if (!bgfx::isValid(IndexBuffer)) { - constexpr const char* errorMsg = "Failed to create index buffer"; - ImpLog(LogLevel::Fatal, LogChannel::Render, errorMsg); - throw std::runtime_error(errorMsg); + Panic(LogChannel::Render, "Failed to create index buffer"); } VertexBufferSpritesLayout.begin() @@ -130,9 +124,7 @@ Renderer::Renderer() { static_cast(Vertices.size() * sizeof(VertexBufferSprites))), VertexBufferSpritesLayout); if (!bgfx::isValid(VertexBuffer)) { - constexpr const char* errorMsg = "Failed to create vertex buffer"; - ImpLog(LogLevel::Fatal, LogChannel::Render, errorMsg); - throw std::runtime_error(errorMsg); + Panic(LogChannel::Render, "Failed to create vertex buffer"); } { diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 9c155df7b..5ca6d8e14 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -12,7 +12,7 @@ namespace Impacto::Bgfx { class Renderer final : public BaseRenderer { public: Renderer(); - ~Renderer() = default; + ~Renderer() { Shutdown(); } void Init() override; void Shutdown() override; diff --git a/src/renderer/bgfx/window.cpp b/src/renderer/bgfx/window.cpp index e423a0125..86ed4c4e3 100644 --- a/src/renderer/bgfx/window.cpp +++ b/src/renderer/bgfx/window.cpp @@ -17,10 +17,8 @@ void Window::Init() { ImpLog(LogLevel::Info, LogChannel::General, "Creating bgfx window\n"); if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { - std::string errorMsg = - fmt::format("SDL initialization failed: {:s}\n", SDL_GetError()); - ImpLog(LogLevel::Fatal, LogChannel::General, "{:s}", errorMsg); - throw std::runtime_error(errorMsg); + Panic(LogChannel::General, "SDL initialization failed: {:s}\n", + SDL_GetError()); } #ifdef SDL_PLATFORM_ANDROID @@ -39,8 +37,6 @@ void Window::Init() { void Window::Shutdown() { SDL_DestroyWindow(SDLWindow); SDL_Quit(); - // TODO: move exit to users - exit(0); } void Window::Draw() { diff --git a/src/renderer/bgfx/window.h b/src/renderer/bgfx/window.h index e175e81b6..767be048c 100644 --- a/src/renderer/bgfx/window.h +++ b/src/renderer/bgfx/window.h @@ -6,6 +6,8 @@ namespace Impacto::Bgfx { class Window final : public BaseWindow { public: + ~Window() { Shutdown(); } + void Init() override; void SetDimensions(int width, int height, int msaa, diff --git a/src/renderer/opengl/3d/renderable3d.cpp b/src/renderer/opengl/3d/renderable3d.cpp index dce337dfc..c9cb34915 100644 --- a/src/renderer/opengl/3d/renderable3d.cpp +++ b/src/renderer/opengl/3d/renderable3d.cpp @@ -828,9 +828,9 @@ void Renderable3D::MainThreadOnLoad() { for (uint32_t i = 0; i < StaticModel->TextureCount; i++) { TexBuffers[i] = StaticModel->Textures[i].Submit(); if (TexBuffers[i] == 0) { - ImpLog(LogLevel::Fatal, LogChannel::Renderable3D, - "Submitting texture {:d} for model {:d} failed\n", i, - StaticModel->Id); + Panic(LogChannel::Renderable3D, + "Submitting texture {:d} for model {:d} failed\n", i, + StaticModel->Id); } } diff --git a/src/renderer/opengl/renderer.cpp b/src/renderer/opengl/renderer.cpp index 6507a331c..702e3530d 100644 --- a/src/renderer/opengl/renderer.cpp +++ b/src/renderer/opengl/renderer.cpp @@ -28,7 +28,7 @@ static CornersQuad FlipUvVertical(CornersQuad quad) { } Renderer::Renderer() { - OpenGLWindow = static_cast(Window); + OpenGLWindow = static_cast(Window.get()); // Generate buffers glGenBuffers(1, &VBO); glGenBuffers(1, &IBO); @@ -217,9 +217,7 @@ bool Renderer::LoadSurf(int surfId, int archiveId, int fileId) { Io::Stream* stream; IoError err = pathRes.Open(&stream); if (err != IoError_OK) { - ImpLog(LogLevel::Fatal, LogChannel::Profile, - "Could not open spritesheet\n"); - Window->Shutdown(); + Panic(LogChannel::Profile, "Could not open spritesheet\n"); } Texture tex{}; diff --git a/src/renderer/opengl/shader.cpp b/src/renderer/opengl/shader.cpp index 91a0460b7..ce5e90c45 100644 --- a/src/renderer/opengl/shader.cpp +++ b/src/renderer/opengl/shader.cpp @@ -105,10 +105,8 @@ GLuint ShaderCompiler::Attach(GLuint program, GLenum shaderType, GLuint shader = glCreateShader(shaderType); if (!shader) { - ImpLog(LogLevel::Fatal, LogChannel::Render, - "Failed to create shader object\n"); SDL_free(source); - return 0; + Panic(LogChannel::Render, "Failed to create shader object\n"); } const GLchar* codeParts[4]; @@ -136,12 +134,9 @@ GLuint ShaderCompiler::Attach(GLuint program, GLenum shaderType, glGetShaderiv(shader, GL_COMPILE_STATUS, &result); if (!result) { glGetShaderInfoLog(shader, sizeof(errorLog), NULL, errorLog); - ImpLog(LogLevel::Fatal, LogChannel::Render, - "Error compiling shader: {:s}\n", errorLog); SDL_free(source); glDeleteShader(shader); - assert(0); - return 0; + Panic(LogChannel::Render, "Error compiling shader: {:s}\n", errorLog); } glAttachShader(program, shader); @@ -154,9 +149,7 @@ GLuint ShaderCompiler::Attach(GLuint program, GLenum shaderType, GLuint ShaderCompiler::Compile(char const* name, ShaderParamMap const& params) { GLuint program = glCreateProgram(); if (!program) { - ImpLog(LogLevel::Fatal, LogChannel::Render, - "Could not create shader program\n"); - return program; + Panic(LogChannel::Render, "Could not create shader program\n"); } ImpLog(LogLevel::Debug, LogChannel::Render, "Compiling shader \"{:s}\"\n", @@ -194,12 +187,10 @@ GLuint ShaderCompiler::Compile(char const* name, ShaderParamMap const& params) { if (!fs) { static GLchar errorLog[1024] = {}; glGetProgramInfoLog(program, sizeof(errorLog), NULL, errorLog); - ImpLog(LogLevel::Fatal, LogChannel::Render, - "Error linking shader program: {:s}\n", errorLog); glDeleteShader(vs); glDeleteProgram(program); ImpStackFree(paramStr); - return 0; + Panic(LogChannel::Render, "Error linking shader program: {:s}\n", errorLog); } ImpStackFree(paramStr); @@ -217,10 +208,8 @@ GLuint ShaderCompiler::Compile(char const* name, ShaderParamMap const& params) { glGetProgramiv(program, GL_LINK_STATUS, &result); if (!result) { glGetProgramInfoLog(program, sizeof(errorLog), NULL, errorLog); - ImpLog(LogLevel::Fatal, LogChannel::Render, - "Error linking shader program: {:s}\n", errorLog); glDeleteProgram(program); - return 0; + Panic(LogChannel::Render, "Error linking shader program: {:s}\n", errorLog); } // TODO: Figure out why this actually doesn't work on macOS @@ -229,10 +218,9 @@ GLuint ShaderCompiler::Compile(char const* name, ShaderParamMap const& params) { glGetProgramiv(program, GL_VALIDATE_STATUS, &result); if (!result) { glGetProgramInfoLog(program, sizeof(errorLog), NULL, errorLog); - ImpLog(LogLevel::Fatal, LogChannel::Render, - "ShaderCompiler program failed to validate: {:s}\n", errorLog); glDeleteProgram(program); - return 0; + Panic(LogChannel::Render, + "ShaderCompiler program failed to validate: {:s}\n", errorLog); } #endif diff --git a/src/renderer/opengl/window.cpp b/src/renderer/opengl/window.cpp index 6adda2542..6349ad55b 100644 --- a/src/renderer/opengl/window.cpp +++ b/src/renderer/opengl/window.cpp @@ -134,10 +134,8 @@ void GLWindow::Init() { SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); #endif if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "SDL initialisation failed: {:s}\n", SDL_GetError()); - Shutdown(); - return; + Panic(LogChannel::General, "SDL initialisation failed: {:s}\n", + SDL_GetError()); } switch (GraphicsApiHint) { @@ -159,10 +157,8 @@ void GLWindow::Init() { } if (GLContext == NULL) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "All options for OpenGL context creation failed\n"); - Shutdown(); - return; + Panic(LogChannel::General, + "All options for OpenGL context creation failed\n"); } SDL_GetWindowSize(SDLWindow, &WindowWidth, &WindowHeight); @@ -179,9 +175,7 @@ void GLWindow::Init() { reinterpret_cast(SDL_GL_GetProcAddress)); } if (!gladOk) { - ImpLog(LogLevel::Fatal, LogChannel::General, - "GLAD initialisation failed\n"); - Shutdown(); + Panic(LogChannel::General, "GLAD initialisation failed\n"); } // At the time of writing, this is on by default on Intel on Windows until we @@ -356,8 +350,6 @@ void GLWindow::Shutdown() { SDL_GL_DestroyContext(GLContext); SDL_DestroyWindow(SDLWindow); SDL_Quit(); - // TODO move exit to users - exit(0); } } // namespace OpenGL diff --git a/src/renderer/opengl/window.h b/src/renderer/opengl/window.h index 586e3af48..eb240465b 100644 --- a/src/renderer/opengl/window.h +++ b/src/renderer/opengl/window.h @@ -7,6 +7,8 @@ namespace OpenGL { class GLWindow : public BaseWindow { public: + ~GLWindow() { Shutdown(); } + void Init() override; void SetDimensions(int width, int height, int msaa, float renderScale) override; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 508b1a5ee..bfbdc0675 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -20,7 +20,7 @@ void CreateRenderer() { switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL case RendererType::OpenGLLegacy: - Renderer = new OpenGL::Renderer(); + Renderer = std::make_unique(); break; #endif #ifndef IMPACTO_DISABLE_BGFX @@ -37,13 +37,11 @@ void CreateRenderer() { #ifndef IMPACTO_DISABLE_METAL case RendererType::Metal: #endif - Renderer = new Bgfx::Renderer(); + Renderer = std::make_unique(); break; #endif // IMPACTO_DISABLE_BGFX default: - ImpLog(LogLevel::Error, LogChannel::Render, - "Unknown or unsupported renderer selected!\n"); - exit(1); + Panic(LogChannel::Render, "Unknown or unsupported renderer selected!\n"); } } diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index eecd91f78..be5add6f8 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -459,8 +459,8 @@ inline void InsertQuad(std::span vertices, }; } -inline BaseRenderer* Renderer; -inline BaseWindow* Window; +inline std::unique_ptr Renderer; +inline std::unique_ptr Window; void CreateRenderer(); diff --git a/src/renderer/window.cpp b/src/renderer/window.cpp index e2c930ec9..9fa4daf62 100644 --- a/src/renderer/window.cpp +++ b/src/renderer/window.cpp @@ -21,7 +21,7 @@ void InitWindow() { switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL case RendererType::OpenGLLegacy: - Window = new OpenGL::GLWindow(); + Window = std::make_unique(); break; #endif #ifndef IMPACTO_DISABLE_BGFX @@ -38,14 +38,13 @@ void InitWindow() { #ifndef IMPACTO_DISABLE_METAL case RendererType::Metal: #endif - Window = new Bgfx::Window(); + Window = std::make_unique(); break; #endif default: - ImpLog(LogLevel::Error, LogChannel::Render, - "Failed to create window: Unknown or unsupported renderer " - "selected!\n"); - exit(1); + Panic(LogChannel::Render, + "Failed to create window: Unknown or unsupported renderer " + "selected!\n"); } Window->Init(); @@ -253,9 +252,8 @@ SDL_Rect BaseWindow::GetDisplayBounds(std::optional flags) { haveBounds = SDL_GetDisplayUsableBounds(display, &result); } if (!haveBounds) { - ImpLog(LogLevel::Fatal, LogChannel::Render, - "Failed to get display bounds: {}.\n", SDL_GetError()); - throw std::runtime_error("Failed to get display info."); + Panic(LogChannel::Render, "Failed to get display bounds: {}.\n", + SDL_GetError()); } return result; } diff --git a/src/renderer/window.h b/src/renderer/window.h index 95cf6b773..26dbf6c3f 100644 --- a/src/renderer/window.h +++ b/src/renderer/window.h @@ -35,6 +35,8 @@ enum GraphicsApi { class BaseWindow { public: + virtual ~BaseWindow() = default; + virtual void Init() = 0; virtual void SetDimensions(int width, int height, int msaa, float renderScale) = 0; diff --git a/src/spritesheet.cpp b/src/spritesheet.cpp index 84a98dbb7..342bed60e 100644 --- a/src/spritesheet.cpp +++ b/src/spritesheet.cpp @@ -1,5 +1,7 @@ #include "spritesheet.h" #include "renderer/renderer.h" +#include "log.h" + #include #include @@ -26,7 +28,8 @@ bool SpriteLoader::LoadSync(int surfId, int archiveId, int fileId) { Io::Stream* stream; IoError err = pathRes.Open(&stream); if (err != IoError_OK) { - Window->Shutdown(); + Panic(LogChannel::IO, "Failed to open asset [MountId: {:d}, Id: {:d}]", + archiveId, fileId); } LoadedTexture.Load(stream); diff --git a/src/texture/texture.cpp b/src/texture/texture.cpp index cdc627c14..7882e756f 100644 --- a/src/texture/texture.cpp +++ b/src/texture/texture.cpp @@ -112,7 +112,7 @@ void Texture::LoadPoliticalCompass() { } uint32_t Texture::Submit(BaseRenderer* renderer) { - if (!renderer) renderer = Renderer; + if (!renderer) renderer = Renderer.get(); ImpLog(LogLevel::Debug, LogChannel::Render, "Submitting texture\n"); if (Buffer.empty()) return std::numeric_limits::max(); diff --git a/src/vm/inst_system.cpp b/src/vm/inst_system.cpp index 48d2b3f24..916d44ae4 100644 --- a/src/vm/inst_system.cpp +++ b/src/vm/inst_system.cpp @@ -684,9 +684,7 @@ VmInstruction(InstTerminate) { StartInstruction; ImpLog(LogLevel::Info, LogChannel::VM, "VM requested shutdown!\n"); - Window->Shutdown(); - // BlockThread; - // ResetInstruction; + Game::Shutdown(); } VmInstruction(InstDebugPrint) { StartInstruction; diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index e0ec54450..fdffe38f1 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -144,8 +144,7 @@ void Init() { break; } default: { - ImpLog(LogLevel::Fatal, LogChannel::VM, "Unsupported instruction set\n"); - Window->Shutdown(); + Panic(LogChannel::VM, "Unsupported instruction set\n"); break; } } From e3ea45b8c630fa5c6247f3a5f866537320d60fa1 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 8 Sep 2026 16:03:51 +0200 Subject: [PATCH 12/60] Allow for changing renderer backend between launcher and game --- src/game.cpp | 25 +++++++++--- src/overlay.cpp | 4 -- src/renderer/bgfx/renderer.cpp | 39 +++++++++++++++++-- src/renderer/bgfx/renderer.h | 9 +++++ src/renderer/opengl/renderer.h | 2 + src/renderer/opengl/window.cpp | 4 ++ src/renderer/renderer.cpp | 2 + src/renderer/renderer.h | 35 +++++++++++++++++ src/renderer/window.cpp | 2 + src/userconfig.h | 33 ---------------- .../backends/imgui_impl_opengl3.cpp | 2 + 11 files changed, 112 insertions(+), 45 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index bd2dd8b61..21d344b2e 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -40,6 +40,8 @@ #include "effects/blur.h" #include "effects/mosaic.h" +#include "userconfig.h" + #include "profile/profile.h" #include "profile/game.h" @@ -76,10 +78,9 @@ using namespace Profile::ScriptVars; namespace Game { -void Init() { - SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); - - WorkQueue::Init(); +static void InitRenderer() { + Renderer.reset(); + Window.reset(); #ifndef IMPACTO_DISABLE_IMGUI IMGUI_CHECKVERSION(); @@ -95,16 +96,30 @@ void Init() { io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; } #endif + InitWindow(); CreateRenderer(); - InitCursors(); #ifndef IMPACTO_DISABLE_IMGUI Overlay::Init(); #endif } +void Init() { + SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); + + WorkQueue::Init(); + + InitRenderer(); + InitCursors(); +} + void InitGameProfile() { + if (UserConfig::AdvancedSettings.ActiveRenderer != Renderer->GetType()) { + // If the active renderer was changed in the launcher, re-init renderer + InitRenderer(); + } + Profile::ConfigureGameProfile(); Profile::Game::Configure(); Profile::Patch::Configure(); diff --git a/src/overlay.cpp b/src/overlay.cpp index 31b4b6920..f95865559 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -31,7 +31,6 @@ using namespace Impacto::Profile::ScriptVars; namespace Impacto::Overlay { -static bool HasInit = false; static std::optional ActiveTab; struct ImgData { @@ -265,12 +264,9 @@ void SetupIcons() { } void Init() { - if (HasInit) return; - SetupStyle(); SetupFonts(); SetupIcons(); - HasInit = true; } static void ShowGamePicker(std::string& selectedGame) { diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index d50dfc352..ffca3e174 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -6,9 +6,12 @@ #include #include -#include #include +#ifndef IMPACTO_DISABLE_IMGUI +#include +#endif + namespace Impacto::Bgfx { constexpr bgfx::ViewId RENDER_VIEW = 0; // Uses render dimensions @@ -172,6 +175,38 @@ void Renderer::Init() { 0.0f, -Profile::Game::DesignWidth, Profile::Game::DesignWidth); } +RendererType Renderer::GetType() const { + switch (bgfx::getRendererType()) { + using enum bgfx::RendererType::Enum; +#ifndef IMPACTO_DISABLE_DIRECT3D + case Direct3D11: + case Direct3D12: + return RendererType::Direct3D; +#endif +#ifndef IMPACTO_DISABLE_METAL + case Metal: + return RendererType::Metal; +#endif +#ifndef IMPACTO_DISABLE_OPENGL + case OpenGLES: + return RendererType::OpenGLES; + case OpenGL: + return RendererType::OpenGL; +#endif +#ifndef IMPACTO_DISABLE_VULKAN + case Vulkan: + return RendererType::Vulkan; +#endif + + default: + break; + } + + Panic(LogChannel::Render, "Unexpected bgfx renderer \"{:s}\"\n", + bgfx::getRendererName(bgfx::getRendererType())); + return RendererType{}; +} + void Renderer::BeginFrame() { bgfx::reset(static_cast(Window->WindowWidth), static_cast(Window->WindowHeight), BGFX_RESET_VSYNC); @@ -224,8 +259,6 @@ void Renderer::Shutdown() { ImGui_Implbgfx_Shutdown(); ImGui::DestroyContext(); #endif - - bgfx::shutdown(); } } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 5ca6d8e14..de27f3251 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -16,6 +16,8 @@ class Renderer final : public BaseRenderer { void Init() override; void Shutdown() override; + RendererType GetType() const override; + #ifndef IMPACTO_DISABLE_IMGUI void ImGuiBeginFrame() override; #endif @@ -130,6 +132,13 @@ class Renderer final : public BaseRenderer { private: void Flush() override {} + // Only call bgfx::shutdown after all managed objects in this class have been + // default-destructed + struct BgfxHandleStruct { + ~BgfxHandleStruct() { bgfx::shutdown(); } + }; + BgfxHandleStruct BgfxHandle; + FrameBuffer BackBufferFrameBuffer; FrameBuffer DrawFrameBuffer; diff --git a/src/renderer/opengl/renderer.h b/src/renderer/opengl/renderer.h index 876337f22..cfe1020ce 100644 --- a/src/renderer/opengl/renderer.h +++ b/src/renderer/opengl/renderer.h @@ -23,6 +23,8 @@ class Renderer : public BaseRenderer { void Init() override; void Shutdown() override; + RendererType GetType() const override { return RendererType::OpenGLLegacy; } + #ifndef IMPACTO_DISABLE_IMGUI void ImGuiBeginFrame() override; #endif diff --git a/src/renderer/opengl/window.cpp b/src/renderer/opengl/window.cpp index 6349ad55b..1e6d928c4 100644 --- a/src/renderer/opengl/window.cpp +++ b/src/renderer/opengl/window.cpp @@ -346,6 +346,10 @@ void GLWindow::Draw() { } void GLWindow::Shutdown() { +#ifndef IMPACTO_DISABLE_IMGUI + ImGui_ImplOpenGL3_Shutdown(); +#endif + CleanFBOs(); SDL_GL_DestroyContext(GLContext); SDL_DestroyWindow(SDLWindow); diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index bfbdc0675..f76923531 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -17,6 +17,8 @@ namespace Impacto { void CreateRenderer() { + Renderer.reset(); + switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL case RendererType::OpenGLLegacy: diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index be5add6f8..0442e0f04 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -9,6 +9,39 @@ #include "nv12frame.h" #include +enum class RendererType : int { +#ifndef IMPACTO_DISABLE_BGFX +#ifndef IMPACTO_DISABLE_OPENGL + OpenGL, + OpenGLES, +#endif +#ifndef IMPACTO_DISABLE_VULKAN + Vulkan, +#endif +#ifndef IMPACTO_DISABLE_DIRECT3D + Direct3D, +#endif +#ifndef IMPACTO_DISABLE_METAL + Metal, +#endif +#endif + +#ifndef IMPACTO_DISABLE_OPENGL + OpenGLLegacy, +#endif +}; + +constexpr inline RendererType DefaultRendererType = +#if defined(SDL_PLATFORM_WIN32) + RendererType::Direct3D; +#elif defined(SDL_PLATFORM_MACOS) + RendererType::Metal; +#elif defined(SDL_PLATFORM_ANDROID) + RendererType::OpenGLES; +#else + RendererType::Vulkan; +#endif + namespace Impacto { inline GraphicsApi GraphicsApiHint; @@ -67,6 +100,8 @@ class BaseRenderer { virtual void Init() = 0; virtual void Shutdown() = 0; + virtual RendererType GetType() const = 0; + #ifndef IMPACTO_DISABLE_IMGUI virtual void ImGuiBeginFrame() = 0; #endif diff --git a/src/renderer/window.cpp b/src/renderer/window.cpp index 9fa4daf62..cc4de275c 100644 --- a/src/renderer/window.cpp +++ b/src/renderer/window.cpp @@ -18,6 +18,8 @@ namespace Impacto { void InitWindow() { + Window.reset(); + switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifndef IMPACTO_DISABLE_OPENGL case RendererType::OpenGLLegacy: diff --git a/src/userconfig.h b/src/userconfig.h index ea2c988d2..0646f372f 100644 --- a/src/userconfig.h +++ b/src/userconfig.h @@ -8,39 +8,6 @@ namespace Impacto { -enum class RendererType : int { -#ifndef IMPACTO_DISABLE_BGFX -#ifndef IMPACTO_DISABLE_OPENGL - OpenGL, - OpenGLES, -#endif -#ifndef IMPACTO_DISABLE_VULKAN - Vulkan, -#endif -#ifndef IMPACTO_DISABLE_DIRECT3D - Direct3D, -#endif -#ifndef IMPACTO_DISABLE_METAL - Metal, -#endif -#endif - -#ifndef IMPACTO_DISABLE_OPENGL - OpenGLLegacy, -#endif -}; - -constexpr inline RendererType DefaultRendererType = -#if defined(SDL_PLATFORM_WIN32) - RendererType::Direct3D; -#elif defined(SDL_PLATFORM_MACOS) - RendererType::Metal; -#elif defined(SDL_PLATFORM_ANDROID) - RendererType::OpenGLES; -#else - RendererType::Vulkan; -#endif - enum class VideoPlayerType : int { None, FFmpeg, diff --git a/vendor/imgui_custom/backends/imgui_impl_opengl3.cpp b/vendor/imgui_custom/backends/imgui_impl_opengl3.cpp index 13a8423aa..ddbd5618f 100644 --- a/vendor/imgui_custom/backends/imgui_impl_opengl3.cpp +++ b/vendor/imgui_custom/backends/imgui_impl_opengl3.cpp @@ -1158,6 +1158,8 @@ void ImGui_ImplOpenGL3_Shutdown() platform_io.ClearRendererHandlers(); IM_DELETE(bd); + io.BackendPlatformUserData = nullptr; + ImGui_ImplOpenGL3_ShutdownLoader(); } From 16623c1980341736ace52c88a7c2445f7d694bdc Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 8 Sep 2026 20:09:57 +0200 Subject: [PATCH 13/60] Selectively enable renderer backends based on target platform --- CMakeLists.txt | 58 +++++++++++++++++++------- portfiles-switch/README.md | 2 +- portfiles-switch/vulkan/vcpkg.json | 2 +- src/config.h.in | 15 ++++--- src/debugmenu.cpp | 16 +++++-- src/game.cpp | 3 ++ src/impacto.h | 2 +- src/log.cpp | 2 +- src/log.h | 4 +- src/renderer/bgfx/renderer.cpp | 55 ++++++++++++++++-------- src/renderer/bgfx/shaders/shaders.h.in | 24 +++++++---- src/renderer/renderer.cpp | 25 ++++++----- src/renderer/renderer.h | 37 +++++++++------- src/renderer/window.cpp | 24 +++++++---- 14 files changed, 182 insertions(+), 87 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 60a874a75..082f50552 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -824,11 +824,35 @@ if (NX OR EMSCRIPTEN) set(BUILD_SHARED_LIBS OFF) endif () -if (NOT WIN32 AND NOT CYGWIN) - set(IMPACTO_DISABLE_DIRECT3D ON) -endif() -if (NOT APPLE) - set(IMPACTO_DISABLE_METAL ON) +if (LINUX) + set(IMPACTO_RENDERER_VULKAN ON) + set(IMPACTO_RENDERER_OPENGL ON) + set(IMPACTO_RENDERER_OPENGLES ON) +elseif (WIN32 OR CYGWIN) + set(IMPACTO_RENDERER_VULKAN ON) + set(IMPACTO_RENDERER_OPENGL ON) + set(IMPACTO_RENDERER_OPENGLES ON) + set(IMPACTO_RENDERER_DIRECT3D11 ON) + set(IMPACTO_RENDERER_DIRECT3D12 ON) +elseif (APPLE) + set(IMPACTO_RENDERER_VULKAN ON) + set(IMPACTO_RENDERER_METAL ON) +elseif (ANDROID) + set(IMPACTO_RENDERER_VULKAN ON) + set(IMPACTO_RENDERER_OPENGLES ON) +elseif (NX) + set(IMPACTO_RENDERER_VULKAN ON) +else () + message(FATAL_ERROR "No renderer backends supplied for target platform") +endif () + +if (IMPACTO_RENDERER_VULKAN OR + IMPACTO_RENDERER_OPENGL OR + IMPACTO_RENDERER_OPENGLES OR + IMPACTO_RENDERER_DIRECT3D11 OR + IMPACTO_RENDERER_DIRECT3D12 OR + IMPACTO_RENDERER_METAL) + set(IMPACTO_RENDERER_BGFX ON) endif () if (IMPACTO_ASAN) @@ -916,7 +940,7 @@ endif () list(APPEND Impacto_Include_Dirs ${CMAKE_CURRENT_SOURCE_DIR}/vendor) list(APPEND Impacto_Include_Dirs ${CMAKE_CURRENT_SOURCE_DIR}/vendor/include) -if (NOT DEFINED IMPACTO_DISABLE_OPENGL) +if (IMPACTO_RENDERER_OPENGL OR IMPACTO_RENDERER_OPENGLES) list(APPEND Impacto_Include_Dirs ${CMAKE_CURRENT_SOURCE_DIR}/vendor/glad/include) if (ANDROID OR NX) @@ -1118,7 +1142,7 @@ if (NOT DEFINED IMPACTO_DISABLE_IMGUI) list(APPEND Impacto_Src src/overlay.cpp) list(APPEND Impacto_Header src/overlay.h) - if (NOT DEFINED IMPACTO_DISABLE_OPENGL) + if (IMPACTO_RENDERER_OPENGL OR IMPACTO_RENDERER_OPENGLES) list(APPEND imgui_src vendor/imgui_custom/backends/imgui_impl_opengl3.cpp ) @@ -1127,25 +1151,31 @@ if (NOT DEFINED IMPACTO_DISABLE_IMGUI) ) endif () - if (NOT DEFINED IMPACTO_DISABLE_VULKAN) + if (IMPACTO_RENDERER_VULKAN) list(APPEND imgui_src ${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp ) endif () - if (NOT DEFINED IMPACTO_DISABLE_DIRECT3D) + if (IMPACTO_RENDERER_DIRECT3D11) + list(APPEND imgui_src + ${imgui_SOURCE_DIR}/backends/imgui_impl_dx11.cpp + ) + endif () + + if (IMPACTO_RENDERER_DIRECT3D12) list(APPEND imgui_src ${imgui_SOURCE_DIR}/backends/imgui_impl_dx12.cpp ) endif () - if (NOT DEFINED IMPACTO_DISABLE_METAL) + if (IMPACTO_RENDERER_METAL) list(APPEND imgui_src ${imgui_SOURCE_DIR}/backends/imgui_impl_metal.mm ) endif () - if (NOT DEFINED IMPACTO_DISABLE_BGFX) + if (IMPACTO_RENDERER_BGFX) FetchContent_Declare( imgui_impl_bgfx URL https://gist.github.com/Madman10K/0ffc9ba203333d3580d467d972bbf8b6/archive/9110d39e126dbd557ad1ff5147526ffeaeb7267c.zip @@ -1181,14 +1211,14 @@ if (NOT DEFINED IMPACTO_DISABLE_IMGUI) target_link_libraries(imgui PRIVATE ${SDL3_LIBRARIES} ${OpenGL_Libs}) - if (NOT DEFINED IMPACTO_DISABLE_BGFX) + if (IMPACTO_RENDERER_BGFX) target_link_libraries(imgui PUBLIC bgfx::bgfx PRIVATE bgfx::bx) endif () list(APPEND Impacto_Lib_Targets imgui) endif () -if (NOT DEFINED IMPACTO_DISABLE_OPENGL) +if (IMPACTO_RENDERER_OPENGL OR IMPACTO_RENDERER_OPENGLES) list(APPEND Impacto_Src src/renderer/opengl/window.cpp src/renderer/opengl/renderer.cpp @@ -1213,7 +1243,7 @@ if (NOT DEFINED IMPACTO_DISABLE_OPENGL) ) endif () -if (NOT DEFINED IMPACTO_DISABLE_BGFX) +if (IMPACTO_RENDERER_BGFX) find_package(bgfx CONFIG REQUIRED) list(APPEND Impacto_Libs bgfx::bgfx) diff --git a/portfiles-switch/README.md b/portfiles-switch/README.md index 48723d972..3f6066bc5 100644 --- a/portfiles-switch/README.md +++ b/portfiles-switch/README.md @@ -23,7 +23,7 @@ nothing and CMake's existing lookup already finds the devkitPro copy: |---------------|--------------------------------------------------------------------------------------------------------| | `zlib` | `find_package(ZLIB)` (CMake module) → devkitPro | | `libass` | `pkg_check_modules(libass)` in impacto's CMakeLists | -| `vulkan` | unused on Switch (`IMPACTO_DISABLE_VULKAN`) | +| `vulkan` | unused on Switch | ## 2. Config-emitting overlays diff --git a/portfiles-switch/vulkan/vcpkg.json b/portfiles-switch/vulkan/vcpkg.json index 0ea2df429..bb8f50c97 100644 --- a/portfiles-switch/vulkan/vcpkg.json +++ b/portfiles-switch/vulkan/vcpkg.json @@ -1,5 +1,5 @@ { "name": "vulkan", "version": "1.1.0", - "description": "Empty overlay for the Switch build: Vulkan is disabled on Switch (IMPACTO_DISABLE_VULKAN), so no Vulkan SDK is needed." + "description": "Empty overlay for the Switch build: Vulkan is disabled on Switch, so no Vulkan SDK is needed." } diff --git a/src/config.h.in b/src/config.h.in index 45806db62..c9c787a42 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -4,11 +4,16 @@ #cmakedefine01 IMPACTO_GL_DEBUG #cmakedefine01 IMPACTO_HAVE_THREADS #cmakedefine01 IMPACTO_USE_SDL_HIGHDPI -#cmakedefine IMPACTO_DISABLE_BGFX -#cmakedefine IMPACTO_DISABLE_VULKAN -#cmakedefine IMPACTO_DISABLE_OPENGL -#cmakedefine IMPACTO_DISABLE_DIRECT3D -#cmakedefine IMPACTO_DISABLE_METAL + +// Renderer backends +#cmakedefine IMPACTO_RENDERER_BGFX +#cmakedefine IMPACTO_RENDERER_VULKAN +#cmakedefine IMPACTO_RENDERER_OPENGL +#cmakedefine IMPACTO_RENDERER_OPENGLES +#cmakedefine IMPACTO_RENDERER_DIRECT3D11 +#cmakedefine IMPACTO_RENDERER_DIRECT3D12 +#cmakedefine IMPACTO_RENDERER_METAL + #cmakedefine IMPACTO_DISABLE_FFMPEG #cmakedefine IMPACTO_DISABLE_OPENAL #cmakedefine IMPACTO_DISABLE_MSPACK diff --git a/src/debugmenu.cpp b/src/debugmenu.cpp index 5933fd285..d8b8bb404 100644 --- a/src/debugmenu.cpp +++ b/src/debugmenu.cpp @@ -44,6 +44,7 @@ static void HelpMarker(const char* desc) { } } +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) static void ImageTooltip(ImVec2 pos, ImTextureID textureId, float texWidth, float texHeight) { if (ImGui::BeginItemTooltip()) { @@ -70,6 +71,7 @@ static void ImageTooltip(ImVec2 pos, ImTextureID textureId, float texWidth, ImGui::EndTooltip(); } } +#endif static void ParseScriptDebugData(uint32_t scriptId) { if (ScriptDebugSource.find(scriptId) != ScriptDebugSource.end()) return; @@ -763,6 +765,7 @@ static ankerl::unordered_dense::map> SpritesBySpriteSheet; static void ShowSprite(const Sprite* sprite) { +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) if (UserConfig::AdvancedSettings.ActiveRenderer == RendererType::OpenGLLegacy) { float texWidth = sprite->Sheet.DesignWidth; @@ -774,6 +777,7 @@ static void ShowSprite(const Sprite* sprite) { ImVec2((sprite->Bounds.X + sprite->Bounds.Width) / texWidth, (sprite->Bounds.Y + sprite->Bounds.Height) / texHeight)); } +#endif } void ShowObjects() { @@ -789,9 +793,10 @@ void ShowObjects() { for (const auto& spriteSheet : Profile::SpriteSheets) { if (ImGui::TreeNode(spriteSheet.first.c_str())) { ImGui::PushID(spriteSheet.second.Texture); +// Only OpenGL for now +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) float texWidth = spriteSheet.second.DesignWidth * 0.4f; float texHeight = spriteSheet.second.DesignHeight * 0.4f; - // Only OpenGL for now if (UserConfig::AdvancedSettings.ActiveRenderer == RendererType::OpenGLLegacy) { ImVec2 pos = ImGui::GetCursorScreenPos(); @@ -800,6 +805,7 @@ void ShowObjects() { ImageTooltip(pos, (ImTextureID)(intptr_t)spriteSheet.second.Texture, texWidth, texHeight); } +#endif ImGui::Spacing(); ImGui::BulletText("Texture: (width: %f, height: %f)", @@ -839,9 +845,10 @@ void ShowObjects() { ImGui::PushID(static_cast(i)); if (ImGui::TreeNode("Background", "Background %zu", i)) { if (Backgrounds[i].Status == LoadStatus::Loaded) { +// Only OpenGL for now +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) float texWidth = Backgrounds[i].BgSprite.Sheet.DesignWidth * 0.4f; float texHeight = Backgrounds[i].BgSprite.Sheet.DesignHeight * 0.4f; - // Only OpenGL for now if (UserConfig::AdvancedSettings.ActiveRenderer == RendererType::OpenGLLegacy) { ImVec2 pos = ImGui::GetCursorScreenPos(); @@ -853,6 +860,7 @@ void ShowObjects() { (ImTextureID)(intptr_t)Backgrounds[i].BgSprite.Sheet.Texture, texWidth, texHeight); } +#endif } ImGui::Spacing(); @@ -893,10 +901,11 @@ void ShowObjects() { ImGui::PushID(static_cast(i)); if (ImGui::TreeNode("Character", "Character %zu", i)) { if (Characters2D[i].Status == LoadStatus::Loaded) { +// Only OpenGL for now +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) float texWidth = Characters2D[i].CharaSprite.Sheet.DesignWidth * 0.4f; float texHeight = Characters2D[i].CharaSprite.Sheet.DesignHeight * 0.4f; - // Only OpenGL for now if (UserConfig::AdvancedSettings.ActiveRenderer == RendererType::OpenGLLegacy) { ImVec2 pos = ImGui::GetCursorScreenPos(); @@ -908,6 +917,7 @@ void ShowObjects() { .CharaSprite.Sheet.Texture, texWidth, texHeight); } +#endif } ImGui::Spacing(); diff --git a/src/game.cpp b/src/game.cpp index 21d344b2e..3e1ac97be 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -7,7 +7,10 @@ #include "log.h" #include "inputsystem.h" #include "debugmenu.h" + +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) #include "renderer/opengl/glc.h" +#endif #ifndef IMPACTO_DISABLE_IMGUI #include "overlay.h" diff --git a/src/impacto.h b/src/impacto.h index 331d5706c..752f67de7 100644 --- a/src/impacto.h +++ b/src/impacto.h @@ -10,7 +10,7 @@ #include -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) #include #endif diff --git a/src/log.cpp b/src/log.cpp index 048daf08f..098d10138 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -164,7 +164,7 @@ std::string GetDefaultLogFile() { #endif } -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) void GLAPIENTRY LogGLMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, diff --git a/src/log.h b/src/log.h index 89053ce04..6b839c3c2 100644 --- a/src/log.h +++ b/src/log.h @@ -4,7 +4,7 @@ #include "util.h" #include "game.h" -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) #include #endif @@ -99,7 +99,7 @@ void ImpLog(LogLevel level, LogChannel channel, fmt::format_string format, #define ImpLogSlow(...) (void)0 #endif -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) void GLAPIENTRY LogGLMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index ffca3e174..89b7c50f5 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -23,21 +23,27 @@ Renderer::Renderer() { initStruct.type = []() -> bgfx::RendererType::Enum { switch (UserConfig::AdvancedSettings.ActiveRenderer) { -#ifndef IMPACTO_DISABLE_OPENGL +#ifdef IMPACTO_RENDERER_OPENGL case RendererType::OpenGL: return bgfx::RendererType::OpenGL; +#endif +#ifdef IMPACTO_RENDERER_OPENGLES case RendererType::OpenGLES: return bgfx::RendererType::OpenGLES; #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN case RendererType::Vulkan: return bgfx::RendererType::Vulkan; #endif -#ifndef IMPACTO_DISABLE_DIRECT3D - case RendererType::Direct3D: +#ifdef IMPACTO_RENDERER_DIRECT3D11 + case RendererType::Direct3D11: + return bgfx::RendererType::Direct3D11; +#endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 + case RendererType::Direct3D12: return bgfx::RendererType::Direct3D12; #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL case RendererType::Metal: return bgfx::RendererType::Metal; #endif @@ -137,23 +143,32 @@ Renderer::Renderer() { ImGui_Implbgfx_Init(IMGUI_VIEW); switch (UserConfig::AdvancedSettings.ActiveRenderer) { -#ifndef IMPACTO_DISABLE_OPENGL +#ifdef IMPACTO_RENDERER_OPENGL case RendererType::OpenGL: + ImGui_ImplSDL3_InitForOpenGL(Window->SDLWindow, nullptr); + break; +#endif +#ifdef IMPACTO_RENDERER_OPENGLES case RendererType::OpenGLES: ImGui_ImplSDL3_InitForOpenGL(Window->SDLWindow, nullptr); break; #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN case RendererType::Vulkan: ImGui_ImplSDL3_InitForVulkan(Window->SDLWindow); break; #endif -#ifndef IMPACTO_DISABLE_DIRECT3D - case RendererType::Direct3D: +#ifdef IMPACTO_RENDERER_DIRECT3D11 + case RendererType::Direct3D11: + ImGui_ImplSDL3_InitForD3D(Window->SDLWindow); + break; +#endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 + case RendererType::Direct3D12: ImGui_ImplSDL3_InitForD3D(Window->SDLWindow); break; #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL case RendererType::Metal: ImGui_ImplSDL3_InitForMetal(Window->SDLWindow); break; @@ -178,22 +193,28 @@ void Renderer::Init() { RendererType Renderer::GetType() const { switch (bgfx::getRendererType()) { using enum bgfx::RendererType::Enum; -#ifndef IMPACTO_DISABLE_DIRECT3D +#ifdef IMPACTO_RENDERER_DIRECT3D11 case Direct3D11: + return RendererType::Direct3D11; + break; +#endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 case Direct3D12: - return RendererType::Direct3D; + return RendererType::Direct3D12; #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL case Metal: return RendererType::Metal; #endif -#ifndef IMPACTO_DISABLE_OPENGL - case OpenGLES: - return RendererType::OpenGLES; +#ifdef IMPACTO_RENDERER_OPENGL case OpenGL: return RendererType::OpenGL; #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_OPENGLES + case OpenGLES: + return RendererType::OpenGLES; +#endif +#ifdef IMPACTO_RENDERER_VULKAN case Vulkan: return RendererType::Vulkan; #endif diff --git a/src/renderer/bgfx/shaders/shaders.h.in b/src/renderer/bgfx/shaders/shaders.h.in index 867614e14..ac5d71809 100644 --- a/src/renderer/bgfx/shaders/shaders.h.in +++ b/src/renderer/bgfx/shaders/shaders.h.in @@ -5,39 +5,45 @@ namespace Impacto::Bgfx { // clang-format off -#ifndef IMPACTO_DISABLE_OPENGL +#ifdef IMPACTO_RENDERER_OPENGL #include "glsl/@SHADER_NAME@.bin.h" +#endif + +#ifdef IMPACTO_RENDERER_OPENGLES #include "essl/@SHADER_NAME@.bin.h" #endif -#ifndef IMPACTO_DISABLE_DIRECT3D -#include "dx10/@SHADER_NAME@.bin.h" +#if defined(IMPACTO_RENDERER_DIRECT3D11) || defined(IMPACTO_RENDERER_DIRECT3D12) #include "dx11/@SHADER_NAME@.bin.h" #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL #include "metal/@SHADER_NAME@.bin.h" #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN #include "spirv/@SHADER_NAME@.bin.h" #endif const inline bgfx::EmbeddedShader @SHADER_BASE_NAME@_shader = { "@SHADER_BASE_NAME@", { -#ifndef IMPACTO_DISABLE_DIRECT3D +#ifdef IMPACTO_RENDERER_DIRECT3D11 BGFX_EMBEDDED_SHADER_DXBC (bgfx::RendererType::Direct3D11, @SHADER_BASE_NAME@) +#endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 BGFX_EMBEDDED_SHADER_DXBC (bgfx::RendererType::Direct3D12, @SHADER_BASE_NAME@) #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL BGFX_EMBEDDED_SHADER_METAL(bgfx::RendererType::Metal, @SHADER_BASE_NAME@) #endif -#ifndef IMPACTO_DISABLE_OPENGL +#ifdef IMPACTO_RENDERER_OPENGLES BGFX_EMBEDDED_SHADER_ESSL (bgfx::RendererType::OpenGLES, @SHADER_BASE_NAME@) +#endif +#ifdef IMPACTO_RENDERER_OPENGL BGFX_EMBEDDED_SHADER_GLSL (bgfx::RendererType::OpenGL, @SHADER_BASE_NAME@) #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN BGFX_EMBEDDED_SHADER_SPIRV(bgfx::RendererType::Vulkan, @SHADER_BASE_NAME@) #endif { bgfx::RendererType::Noop, (const uint8_t*)"VSH\x5\x0\x0\x0\x0\x0\x0", 10 }, diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index f76923531..64dc64c2e 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -4,11 +4,11 @@ #include "../userconfig.h" #include "../log.h" -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) #include "opengl/renderer.h" #endif -#ifndef IMPACTO_DISABLE_BGFX +#ifdef IMPACTO_RENDERER_BGFX #include "bgfx/renderer.h" #endif @@ -20,28 +20,33 @@ void CreateRenderer() { Renderer.reset(); switch (UserConfig::AdvancedSettings.ActiveRenderer) { -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) case RendererType::OpenGLLegacy: Renderer = std::make_unique(); break; #endif -#ifndef IMPACTO_DISABLE_BGFX -#ifndef IMPACTO_DISABLE_OPENGL +#ifdef IMPACTO_RENDERER_BGFX +#ifdef IMPACTO_RENDERER_OPENGL case RendererType::OpenGL: +#endif +#ifdef IMPACTO_RENDERER_OPENGLES case RendererType::OpenGLES: #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN case RendererType::Vulkan: #endif -#ifndef IMPACTO_DISABLE_DIRECT3D - case RendererType::Direct3D: +#ifdef IMPACTO_RENDERER_DIRECT3D11 + case RendererType::Direct3D11: +#endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 + case RendererType::Direct3D12: #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL case RendererType::Metal: #endif Renderer = std::make_unique(); break; -#endif // IMPACTO_DISABLE_BGFX +#endif // IMPACTO_RENDERER_BGFX default: Panic(LogChannel::Render, "Unknown or unsupported renderer selected!\n"); } diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 0442e0f04..ac54c4769 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -10,36 +10,43 @@ #include enum class RendererType : int { -#ifndef IMPACTO_DISABLE_BGFX -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) + OpenGLLegacy, +#endif +#ifdef IMPACTO_RENDERER_OPENGL OpenGL, +#endif +#ifdef IMPACTO_RENDERER_OPENGLES OpenGLES, #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN Vulkan, #endif -#ifndef IMPACTO_DISABLE_DIRECT3D - Direct3D, -#endif -#ifndef IMPACTO_DISABLE_METAL - Metal, +#ifdef IMPACTO_RENDERER_DIRECT3D11 + Direct3D11, #endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 + Direct3D12, #endif - -#ifndef IMPACTO_DISABLE_OPENGL - OpenGLLegacy, +#ifdef IMPACTO_RENDERER_METAL + Metal, #endif }; constexpr inline RendererType DefaultRendererType = -#if defined(SDL_PLATFORM_WIN32) - RendererType::Direct3D; -#elif defined(SDL_PLATFORM_MACOS) +#if defined(SDL_PLATFORM_LINUX) + RendererType::Vulkan; +#elif defined(SDL_PLATFORM_WINDOWS) + RendererType::Direct3D12; +#elif defined(SDL_PLATFORM_APPLE) RendererType::Metal; #elif defined(SDL_PLATFORM_ANDROID) RendererType::OpenGLES; -#else +#elif defined(__SWITCH__) RendererType::Vulkan; +#else + RendererType{}; +static_assert(false && "No default renderer supplied for target renderer"); #endif namespace Impacto { diff --git a/src/renderer/window.cpp b/src/renderer/window.cpp index cc4de275c..8d4be3782 100644 --- a/src/renderer/window.cpp +++ b/src/renderer/window.cpp @@ -9,9 +9,12 @@ #include #include #include "../inputsystem.h" + +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) #include "opengl/window.h" +#endif -#ifndef IMPACTO_DISABLE_BGFX +#ifdef IMPACTO_RENDERER_BGFX #include "bgfx/window.h" #endif @@ -21,23 +24,28 @@ void InitWindow() { Window.reset(); switch (UserConfig::AdvancedSettings.ActiveRenderer) { -#ifndef IMPACTO_DISABLE_OPENGL +#if defined(IMPACTO_RENDERER_OPENGL) || defined(IMPACTO_RENDERER_OPENGLES) case RendererType::OpenGLLegacy: Window = std::make_unique(); break; #endif -#ifndef IMPACTO_DISABLE_BGFX -#ifndef IMPACTO_DISABLE_OPENGL +#ifdef IMPACTO_RENDERER_BGFX +#ifdef IMPACTO_RENDERER_OPENGL case RendererType::OpenGL: +#endif +#ifdef IMPACTO_RENDERER_OPENGLES case RendererType::OpenGLES: #endif -#ifndef IMPACTO_DISABLE_VULKAN +#ifdef IMPACTO_RENDERER_VULKAN case RendererType::Vulkan: #endif -#ifndef IMPACTO_DISABLE_DIRECT3D - case RendererType::Direct3D: +#ifdef IMPACTO_RENDERER_DIRECT3D11 + case RendererType::Direct3D11: +#endif +#ifdef IMPACTO_RENDERER_DIRECT3D12 + case RendererType::Direct3D12: #endif -#ifndef IMPACTO_DISABLE_METAL +#ifdef IMPACTO_RENDERER_METAL case RendererType::Metal: #endif Window = std::make_unique(); From ff3f77ca1bd2172c119682e09e9a451a8856280c Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 8 Sep 2026 21:29:37 +0200 Subject: [PATCH 14/60] Improve bgfx RAII --- src/renderer/bgfx/framebuffer.cpp | 21 +++++++-------------- src/renderer/bgfx/framebuffer.h | 14 ++++++-------- src/renderer/bgfx/renderer.cpp | 7 +++++-- src/renderer/bgfx/renderer.h | 4 ++-- src/renderer/bgfx/shader.h | 23 +++++++++-------------- src/renderer/bgfx/uniform.h | 17 +++++++---------- 6 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/renderer/bgfx/framebuffer.cpp b/src/renderer/bgfx/framebuffer.cpp index 06848bf43..cae5eb58b 100644 --- a/src/renderer/bgfx/framebuffer.cpp +++ b/src/renderer/bgfx/framebuffer.cpp @@ -9,9 +9,7 @@ FrameBuffer::FrameBuffer(FrameBuffer&& other) { *this = std::move(other); } FrameBuffer& FrameBuffer::operator=(FrameBuffer&& other) { if (&other == this) return *this; Reset(true); - if (!other.IsInit) return *this; - IsInit = true; FrameBufferHandle = other.FrameBufferHandle; ColorAttachment = other.ColorAttachment; DepthStencilAttachment = other.DepthStencilAttachment; @@ -31,17 +29,15 @@ FrameBuffer::FrameBuffer(const uint16_t width, const uint16_t height) bgfx::TextureFormat::D24S8, BGFX_TEXTURE_RT)) { assert(bgfx::isValid(ColorAttachment)); - assert(bgfx::isValid(*DepthStencilAttachment)); + assert(bgfx::isValid(DepthStencilAttachment)); std::array attachments; attachments[0].init(ColorAttachment); - attachments[1].init(*DepthStencilAttachment); + attachments[1].init(DepthStencilAttachment); FrameBufferHandle = bgfx::createFrameBuffer( static_cast(attachments.size()), attachments.data(), true); assert(bgfx::isValid(FrameBufferHandle)); - - IsInit = true; } FrameBuffer FrameBuffer::CreateBackBufferFrameBuffer() { @@ -56,20 +52,17 @@ FrameBuffer FrameBuffer::CreateBackBufferFrameBuffer() { bgfx::createFrameBuffer(1, &frameBuffer.ColorAttachment, true); assert(bgfx::isValid(frameBuffer.FrameBufferHandle)); - frameBuffer.IsInit = true; - return frameBuffer; } void FrameBuffer::Reset(bool cleanUpResources) { - if (!IsInit) return; - IsInit = false; - - DepthStencilAttachment.reset(); - if (cleanUpResources) { - bgfx::destroy(FrameBufferHandle); + if (bgfx::isValid(FrameBufferHandle)) bgfx::destroy(FrameBufferHandle); } + + FrameBufferHandle.idx = bgfx::kInvalidHandle; + ColorAttachment.idx = bgfx::kInvalidHandle; + DepthStencilAttachment.idx = bgfx::kInvalidHandle; } } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/framebuffer.h b/src/renderer/bgfx/framebuffer.h index 42a4d0001..b9e98fd3a 100644 --- a/src/renderer/bgfx/framebuffer.h +++ b/src/renderer/bgfx/framebuffer.h @@ -25,26 +25,24 @@ class FrameBuffer { operator bgfx::FrameBufferHandle() { return GetFrameBufferHandle(); } [[nodiscard]] bgfx::FrameBufferHandle GetFrameBufferHandle() { - assert(IsInit && bgfx::isValid(FrameBufferHandle)); + assert(bgfx::isValid(FrameBufferHandle)); return FrameBufferHandle; } [[nodiscard]] bgfx::TextureHandle GetColorAttachmentHandle() { - assert(IsInit && bgfx::isValid(ColorAttachment)); + assert(bgfx::isValid(ColorAttachment)); return ColorAttachment; } [[nodiscard]] bgfx::TextureHandle GetTexture() { - assert(IsInit && bgfx::isValid(FrameBufferHandle)); + assert(bgfx::isValid(FrameBufferHandle)); return bgfx::getTexture(FrameBufferHandle, 0); } private: - bool IsInit = false; - - bgfx::FrameBufferHandle FrameBufferHandle; - bgfx::TextureHandle ColorAttachment; - std::optional DepthStencilAttachment; + bgfx::FrameBufferHandle FrameBufferHandle = {bgfx::kInvalidHandle}; + bgfx::TextureHandle ColorAttachment = {bgfx::kInvalidHandle}; + bgfx::TextureHandle DepthStencilAttachment = {bgfx::kInvalidHandle}; void Reset(bool cleanUpResources); }; diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 89b7c50f5..914e3a96b 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -272,8 +272,11 @@ void Renderer::ImGuiBeginFrame() { #endif void Renderer::Shutdown() { - bgfx::destroy(IndexBuffer); - bgfx::destroy(VertexBuffer); + if (bgfx::isValid(IndexBuffer)) bgfx::destroy(IndexBuffer); + IndexBuffer.idx = bgfx::kInvalidHandle; + + if (bgfx::isValid(VertexBuffer)) bgfx::destroy(VertexBuffer); + VertexBuffer.idx = bgfx::kInvalidHandle; #ifndef IMPACTO_DISABLE_IMGUI ImGui_ImplSDL3_Shutdown(); diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index de27f3251..c57d0bc65 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -142,8 +142,8 @@ class Renderer final : public BaseRenderer { FrameBuffer BackBufferFrameBuffer; FrameBuffer DrawFrameBuffer; - bgfx::DynamicIndexBufferHandle IndexBuffer; - bgfx::DynamicVertexBufferHandle VertexBuffer; + bgfx::DynamicIndexBufferHandle IndexBuffer = {bgfx::kInvalidHandle}; + bgfx::DynamicVertexBufferHandle VertexBuffer = {bgfx::kInvalidHandle}; std::vector Indices; std::vector Vertices; diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h index caf24b51b..3766dafaf 100644 --- a/src/renderer/bgfx/shader.h +++ b/src/renderer/bgfx/shader.h @@ -33,7 +33,7 @@ class ShaderProgram { operator bgfx::ProgramHandle() { return GetProgramHandle(); } [[nodiscard]] bgfx::ProgramHandle GetProgramHandle() { - assert(IsInit && bgfx::isValid(ProgramHandle)); + assert(bgfx::isValid(ProgramHandle)); return ProgramHandle; } @@ -42,12 +42,10 @@ class ShaderProgram { } private: - bool IsInit = false; + bgfx::ProgramHandle ProgramHandle = {bgfx::kInvalidHandle}; - bgfx::ProgramHandle ProgramHandle; - - bgfx::ShaderHandle VertexShader; - bgfx::ShaderHandle FragmentShader; + bgfx::ShaderHandle VertexShader = {bgfx::kInvalidHandle}; + bgfx::ShaderHandle FragmentShader = {bgfx::kInvalidHandle}; void Reset(bool cleanUpResources); @@ -59,9 +57,7 @@ ShaderProgram& ShaderProgram::operator=( ShaderProgram&& other) { if (&other == this) return *this; Reset(true); - if (!other.IsInit) return *this; - IsInit = true; ProgramHandle = other.ProgramHandle; VertexShader = other.VertexShader; FragmentShader = other.FragmentShader; @@ -86,18 +82,17 @@ ShaderProgram::ShaderProgram(const bgfx::EmbeddedShader& vertexShader, assert(bgfx::isValid(ProgramHandle)); ShaderUniformsState.emplace(ProgramHandle); - - IsInit = true; } template void ShaderProgram::Reset(bool cleanUpResources) { - if (!IsInit) return; - IsInit = false; - if (cleanUpResources) { - bgfx::destroy(ProgramHandle); + if (bgfx::isValid(ProgramHandle)) bgfx::destroy(ProgramHandle); } + + ProgramHandle.idx = bgfx::kInvalidHandle; + VertexShader.idx = bgfx::kInvalidHandle; + FragmentShader.idx = bgfx::kInvalidHandle; } } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h index 12de988c8..7e2c89691 100644 --- a/src/renderer/bgfx/uniform.h +++ b/src/renderer/bgfx/uniform.h @@ -41,10 +41,9 @@ struct UniformHandle { UniformHandle& operator=(UniformHandle&& other) { if (this == &other) return *this; Reset(); - if (!other.Handle.has_value()) return *this; Handle = other.Handle; - other.Handle.reset(); + other.Handle.idx = bgfx::kInvalidHandle; return *this; } @@ -52,23 +51,21 @@ struct UniformHandle { UniformHandle(const char* name, bgfx::UniformType::Enum type, uint16_t num = 1) : Handle(bgfx::createUniform(name, type, num)) { - assert(bgfx::isValid(*Handle)); + assert(bgfx::isValid(Handle)); } bgfx::UniformHandle GetHandle() { - assert(bgfx::isValid(*Handle)); - return *Handle; + assert(bgfx::isValid(Handle)); + return Handle; } operator bgfx::UniformHandle() { return GetHandle(); } private: - std::optional Handle; + bgfx::UniformHandle Handle = {bgfx::kInvalidHandle}; void Reset() { - if (!Handle.has_value()) return; - - bgfx::destroy(*Handle); - Handle.reset(); + if (bgfx::isValid(Handle)) bgfx::destroy(Handle); + Handle.idx = bgfx::kInvalidHandle; } }; From 03e7899a88f1c6f940c6b6555b30c56a86113110 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 8 Sep 2026 23:09:16 +0200 Subject: [PATCH 15/60] Implement textures --- CMakeLists.txt | 2 ++ src/renderer/bgfx/renderer.cpp | 18 ++++++++++ src/renderer/bgfx/renderer.h | 13 +++++--- src/renderer/bgfx/texture.cpp | 57 ++++++++++++++++++++++++++++++++ src/renderer/bgfx/texture.h | 41 +++++++++++++++++++++++ src/renderer/opengl/renderer.cpp | 6 ++-- src/renderer/opengl/renderer.h | 4 +-- src/renderer/renderer.h | 4 +-- src/texture/texture.cpp | 3 +- 9 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 src/renderer/bgfx/texture.cpp create mode 100644 src/renderer/bgfx/texture.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 082f50552..d3b0936b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1250,12 +1250,14 @@ if (IMPACTO_RENDERER_BGFX) list(APPEND Impacto_Src src/renderer/bgfx/framebuffer.cpp src/renderer/bgfx/renderer.cpp + src/renderer/bgfx/texture.cpp src/renderer/bgfx/window.cpp ) list(APPEND Impacto_Header src/renderer/bgfx/framebuffer.h src/renderer/bgfx/renderer.h src/renderer/bgfx/shader.h + src/renderer/bgfx/texture.h src/renderer/bgfx/window.h src/renderer/bgfx/shaders/sprite.h diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 914e3a96b..93325173c 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -271,6 +271,24 @@ void Renderer::ImGuiBeginFrame() { } #endif +uint32_t Renderer::SubmitTexture(const TexFmt format, + const std::span buffer, + const int width, const int height) { + static uint32_t curTextureId = 1; + const uint32_t textureId = curTextureId++; + + Textures.emplace(textureId, + Texture(format, buffer, static_cast(width), + static_cast(height))); + + return textureId; +} + +void Renderer::FreeTexture(const uint32_t id) { + assert(Textures.contains(id)); + Textures.erase(id); +} + void Renderer::Shutdown() { if (bgfx::isValid(IndexBuffer)) bgfx::destroy(IndexBuffer); IndexBuffer.idx = bgfx::kInvalidHandle; diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index c57d0bc65..fbbc79141 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -4,9 +4,12 @@ #include "framebuffer.h" #include "shader.h" +#include "texture.h" #include +#include + namespace Impacto::Bgfx { class Renderer final : public BaseRenderer { @@ -29,16 +32,14 @@ class Renderer final : public BaseRenderer { uint32_t MapSpriteSheet(SpriteSheet const& sheet) override { return 0; } bool LoadSurf(int surfId, int archiveId, int fileId) override { return true; } void UnloadSurf(int surfId) override {} - uint32_t SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) override { - return 0; - } + uint32_t SubmitTexture(TexFmt format, std::span buffer, + int width, int height) override; int GetSpriteSheetImage(SpriteSheet const& sheet, std::span outBuffer) override { return 0; } - void FreeTexture(uint32_t id) override {} + void FreeTexture(uint32_t id) override; YUVFrame* CreateYUVFrame(float width, float height) override { return nullptr; } @@ -154,6 +155,8 @@ class Renderer final : public BaseRenderer { glm::mat4 BackBufferProjectionMatrix; std::optional> SpriteShader; + + std::map Textures; }; } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/texture.cpp b/src/renderer/bgfx/texture.cpp new file mode 100644 index 000000000..107bed12d --- /dev/null +++ b/src/renderer/bgfx/texture.cpp @@ -0,0 +1,57 @@ +#include "texture.h" + +#include "../../log.h" + +namespace Impacto::Bgfx { + +Texture& Texture::operator=(Texture&& other) { + if (this == &other) return *this; + Reset(true); + + Handle = other.Handle; + + other.Reset(false); + + return *this; +} + +Texture::Texture(const TexFmt format, const std::span data, + const size_t width, const size_t height) { + const bgfx::TextureFormat::Enum bgfxTextureFormat = + [format]() -> bgfx::TextureFormat::Enum { + switch (format) { + case TexFmt_RGB: + return bgfx::TextureFormat::RGB8; + case TexFmt_RGBA: + return bgfx::TextureFormat::RGBA8; + case TexFmt_U8: + return bgfx::TextureFormat::R8; + } + assert(false); + return bgfx::TextureFormat::RGBA8; + }(); + + constexpr uint64_t textureFlags = BGFX_SAMPLER_MIN_ANISOTROPIC | // + BGFX_SAMPLER_MAG_ANISOTROPIC | // + BGFX_SAMPLER_UVW_CLAMP; + + Handle = bgfx::createTexture2D( + static_cast(width), static_cast(height), false, 1, + bgfxTextureFormat, textureFlags, + bgfx::copy(data.data(), static_cast(data.size_bytes()))); + + if (!bgfx::isValid(Handle)) { + ImpLog(LogLevel::Error, LogChannel::Render, "Failed to create texture."); + assert(false); + } +} + +void Texture::Reset(const bool cleanUpResources) { + if (cleanUpResources) { + if (bgfx::isValid(Handle)) bgfx::destroy(Handle); + } + + Handle.idx = bgfx::kInvalidHandle; +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/texture.h b/src/renderer/bgfx/texture.h new file mode 100644 index 000000000..10d6eff35 --- /dev/null +++ b/src/renderer/bgfx/texture.h @@ -0,0 +1,41 @@ +#pragma once + +#include "../../texture/texture.h" + +#include + +#include +#include + +namespace Impacto::Bgfx { + +class Texture { + public: + Texture() = delete; + Texture(Texture&) = delete; + Texture(Texture&& other) { *this = std::move(other); } + ~Texture() { Reset(true); } + + Texture& operator=(Texture&) = delete; + Texture& operator=(Texture&&); + + bool operator==(const Texture& other) const { + return other.Handle.idx == Handle.idx; + } + + Texture(TexFmt format, std::span data, size_t width, + size_t height); + + operator bgfx::TextureHandle() { return GetTextureHandle(); } + bgfx::TextureHandle GetTextureHandle() { + assert(bgfx::isValid(Handle)); + return Handle; + } + + private: + bgfx::TextureHandle Handle = {bgfx::kInvalidHandle}; + + void Reset(bool cleanUpResources); +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/opengl/renderer.cpp b/src/renderer/opengl/renderer.cpp index 702e3530d..57c2885c6 100644 --- a/src/renderer/opengl/renderer.cpp +++ b/src/renderer/opengl/renderer.cpp @@ -250,8 +250,8 @@ void Renderer::UnloadSurf(int surfId) { SurfToId.erase(surfId); } -uint32_t Renderer::SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) { +uint32_t Renderer::SubmitTexture(TexFmt format, std::span buffer, + int width, int height) { GLint prevBound; uint32_t result; glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevBound); @@ -293,7 +293,7 @@ uint32_t Renderer::SubmitTexture(TexFmt format, uint8_t* buffer, int width, } }(); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, texFormat, - GL_UNSIGNED_BYTE, buffer); + GL_UNSIGNED_BYTE, buffer.data()); // Build mip chain // TODO do this ourselves outside of Submit(), this can easily cause a diff --git a/src/renderer/opengl/renderer.h b/src/renderer/opengl/renderer.h index cfe1020ce..5a26b943d 100644 --- a/src/renderer/opengl/renderer.h +++ b/src/renderer/opengl/renderer.h @@ -36,8 +36,8 @@ class Renderer : public BaseRenderer { uint32_t MapSpriteSheet(SpriteSheet const& sheet) override; bool LoadSurf(int surfId, int archiveId, int fileId) override; void UnloadSurf(int surfId) override; - uint32_t SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) override; + uint32_t SubmitTexture(TexFmt format, std::span buffer, + int width, int height) override; int GetSpriteSheetImage(SpriteSheet const& sheet, std::span outBuffer) override; void FreeTexture(uint32_t id) override; diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index ac54c4769..9c33ce682 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -127,8 +127,8 @@ class BaseRenderer { virtual uint32_t MapSpriteSheet(SpriteSheet const& sheet) = 0; virtual bool LoadSurf(int surfId, int archiveId, int fileId) = 0; virtual void UnloadSurf(int surfId) = 0; - virtual uint32_t SubmitTexture(TexFmt format, uint8_t* buffer, int width, - int height) = 0; + virtual uint32_t SubmitTexture(TexFmt format, std::span buffer, + int width, int height) = 0; std::vector GetSpriteSheetImage(SpriteSheet const& sheet) { std::vector result( diff --git a/src/texture/texture.cpp b/src/texture/texture.cpp index 7882e756f..c9178c85f 100644 --- a/src/texture/texture.cpp +++ b/src/texture/texture.cpp @@ -117,8 +117,7 @@ uint32_t Texture::Submit(BaseRenderer* renderer) { if (Buffer.empty()) return std::numeric_limits::max(); - uint32_t result = - renderer->SubmitTexture(Format, Buffer.data(), Width, Height); + uint32_t result = renderer->SubmitTexture(Format, Buffer, Width, Height); // TODO I meant to do this elsewhere but we gotta do it somewhere Buffer.clear(); From e0eb66cdf231f62905192922e7a17e9ec8de48ea Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 16:40:03 +0200 Subject: [PATCH 16/60] Add sampler uniform handling and split shader program based on vertex and fragment types --- CMakeLists.txt | 3 +- src/renderer/bgfx/renderer.cpp | 6 +- src/renderer/bgfx/renderer.h | 4 +- src/renderer/bgfx/shader.h | 76 ++++++++++----- src/renderer/bgfx/shaders/fs_sprite.h | 19 ++++ src/renderer/bgfx/shaders/sprite.h | 17 ---- src/renderer/bgfx/shaders/vs_sprite.h | 13 +++ src/renderer/bgfx/texture.h | 2 +- src/renderer/bgfx/uniform.h | 128 +++++++++++++++++--------- 9 files changed, 177 insertions(+), 91 deletions(-) create mode 100644 src/renderer/bgfx/shaders/fs_sprite.h delete mode 100644 src/renderer/bgfx/shaders/sprite.h create mode 100644 src/renderer/bgfx/shaders/vs_sprite.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d3b0936b2..e7400c078 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1260,7 +1260,8 @@ if (IMPACTO_RENDERER_BGFX) src/renderer/bgfx/texture.h src/renderer/bgfx/window.h - src/renderer/bgfx/shaders/sprite.h + src/renderer/bgfx/shaders/vs_sprite.h + src/renderer/bgfx/shaders/fs_sprite.h ) set(Bgfx_Vertex_Shaders diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 93325173c..cdca58b9b 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -136,10 +136,8 @@ Renderer::Renderer() { Panic(LogChannel::Render, "Failed to create vertex buffer"); } - { - using enum ShaderProgramType; - SpriteShader.emplace(vs_sprite_shader, fs_sprite_shader); - } + const auto flush = [this]() { Flush(); }; + SpriteShader.emplace(vs_sprite_shader, fs_sprite_shader, flush); ImGui_Implbgfx_Init(IMGUI_VIEW); switch (UserConfig::AdvancedSettings.ActiveRenderer) { diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index fbbc79141..daa458686 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -154,7 +154,9 @@ class Renderer final : public BaseRenderer { glm::mat4 ProjectionMatrix; glm::mat4 BackBufferProjectionMatrix; - std::optional> SpriteShader; + std::optional< + ShaderProgram> + SpriteShader; std::map Textures; }; diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h index 3766dafaf..aabf60be5 100644 --- a/src/renderer/bgfx/shader.h +++ b/src/renderer/bgfx/shader.h @@ -12,33 +12,48 @@ #include "../../log.h" -#include "shaders/sprite.h" +#include "shaders/vs_sprite.h" +#include "shaders/fs_sprite.h" namespace Impacto::Bgfx { -template -class ShaderProgram { +class ShaderProgramInterface { + public: + operator bgfx::ProgramHandle() { return GetProgramHandle(); } + + [[nodiscard]] virtual bgfx::ProgramHandle GetProgramHandle() = 0; +}; + +template +class ShaderProgram final : public ShaderProgramInterface { public: ShaderProgram() = delete; - ShaderProgram(const ShaderProgram&) = delete; - ShaderProgram(ShaderProgram&& other) { *this = std::move(other); } + ShaderProgram(const ShaderProgram&) = + delete; + ShaderProgram(ShaderProgram&& other) { + *this = std::move(other); + } ~ShaderProgram() { Reset(true); } - ShaderProgram& operator=(const ShaderProgram&) = delete; - ShaderProgram& operator=(ShaderProgram&&); + ShaderProgram& operator=( + const ShaderProgram&) = delete; + ShaderProgram& operator=( + ShaderProgram&&); ShaderProgram(const bgfx::EmbeddedShader& vertexShader, - const bgfx::EmbeddedShader& fragmentShader); - - operator bgfx::ProgramHandle() { return GetProgramHandle(); } + const bgfx::EmbeddedShader& fragmentShader, + std::function flush); - [[nodiscard]] bgfx::ProgramHandle GetProgramHandle() { + [[nodiscard]] bgfx::ProgramHandle GetProgramHandle() override { assert(bgfx::isValid(ProgramHandle)); return ProgramHandle; } - void SubmitUniforms(const Uniforms& newUniforms) { - ShaderUniformsState->Submit(newUniforms); + void SubmitUniforms(const Uniforms& newVertexUniforms, + const Uniforms& newFragmentUniforms) { + VertexUniformsState->Submit(newVertexUniforms); + FragmentUniformsState->Submit(newFragmentUniforms); } private: @@ -49,12 +64,15 @@ class ShaderProgram { void Reset(bool cleanUpResources); - std::optional> ShaderUniformsState; + std::optional> VertexUniformsState; + std::optional> FragmentUniformsState; }; -template -ShaderProgram& ShaderProgram::operator=( - ShaderProgram&& other) { +template +ShaderProgram& +ShaderProgram::operator=( + ShaderProgram&& other) { if (&other == this) return *this; Reset(true); @@ -62,14 +80,20 @@ ShaderProgram& ShaderProgram::operator=( VertexShader = other.VertexShader; FragmentShader = other.FragmentShader; + VertexUniformsState = std::move(other.VertexUniformsState); + FragmentUniformsState = std::move(other.FragmentUniformsState); + other.Reset(false); return *this; } -template -ShaderProgram::ShaderProgram(const bgfx::EmbeddedShader& vertexShader, - const bgfx::EmbeddedShader& fragmentShader) { +template +ShaderProgram::ShaderProgram( + const bgfx::EmbeddedShader& vertexShader, + const bgfx::EmbeddedShader& fragmentShader, + const std::function flush) { VertexShader = bgfx::createEmbeddedShader( &vertexShader, bgfx::getRendererType(), vertexShader.name); assert(bgfx::isValid(VertexShader)); @@ -81,11 +105,14 @@ ShaderProgram::ShaderProgram(const bgfx::EmbeddedShader& vertexShader, ProgramHandle = bgfx::createProgram(VertexShader, FragmentShader, true); assert(bgfx::isValid(ProgramHandle)); - ShaderUniformsState.emplace(ProgramHandle); + VertexUniformsState.emplace(ProgramHandle, flush); + FragmentUniformsState.emplace(ProgramHandle, flush); } -template -void ShaderProgram::Reset(bool cleanUpResources) { +template +void ShaderProgram::Reset( + bool cleanUpResources) { if (cleanUpResources) { if (bgfx::isValid(ProgramHandle)) bgfx::destroy(ProgramHandle); } @@ -93,6 +120,9 @@ void ShaderProgram::Reset(bool cleanUpResources) { ProgramHandle.idx = bgfx::kInvalidHandle; VertexShader.idx = bgfx::kInvalidHandle; FragmentShader.idx = bgfx::kInvalidHandle; + + VertexUniformsState.reset(); + FragmentUniformsState.reset(); } } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shaders/fs_sprite.h b/src/renderer/bgfx/shaders/fs_sprite.h new file mode 100644 index 000000000..ed6eac047 --- /dev/null +++ b/src/renderer/bgfx/shaders/fs_sprite.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../uniform.h" + +namespace Impacto::Bgfx { + +template <> +struct Uniforms { + bgfx::TextureHandle Texture = {bgfx::kInvalidHandle}; + glm::vec3 ColorShift = glm::vec3(0.0f); +}; + +template <> +struct UniformHandles { + DECLARE_SAMPLER_HANDLE(FragmentShaderType::Sprite, Texture, s_texture, 0); + DECLARE_UNIFORM_HANDLE(FragmentShaderType::Sprite, ColorShift, u_colorShift); +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shaders/sprite.h b/src/renderer/bgfx/shaders/sprite.h deleted file mode 100644 index 7ad10e00b..000000000 --- a/src/renderer/bgfx/shaders/sprite.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "../uniform.h" - -namespace Impacto::Bgfx { - -template <> -struct Uniforms { - glm::vec3 ColorShift = glm::vec3(0.0f); -}; - -template <> -struct UniformHandles { - DECLARE_UNIFORM_HANDLE(Sprite, ColorShift, u_colorShift, 1); -}; - -} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shaders/vs_sprite.h b/src/renderer/bgfx/shaders/vs_sprite.h new file mode 100644 index 000000000..b27bb36c4 --- /dev/null +++ b/src/renderer/bgfx/shaders/vs_sprite.h @@ -0,0 +1,13 @@ +#pragma once + +#include "../uniform.h" + +namespace Impacto::Bgfx { + +template <> +struct Uniforms {}; + +template <> +struct UniformHandles {}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/texture.h b/src/renderer/bgfx/texture.h index 10d6eff35..0192e0d0e 100644 --- a/src/renderer/bgfx/texture.h +++ b/src/renderer/bgfx/texture.h @@ -11,7 +11,7 @@ namespace Impacto::Bgfx { class Texture { public: - Texture() = delete; + Texture() = default; Texture(Texture&) = delete; Texture(Texture&& other) { *this = std::move(other); } ~Texture() { Reset(true); } diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h index 7e2c89691..934fb615c 100644 --- a/src/renderer/bgfx/uniform.h +++ b/src/renderer/bgfx/uniform.h @@ -2,32 +2,82 @@ #include #include +#include #include "../renderer.h" +inline bool operator!=(const bgfx::TextureHandle& lhs, + const bgfx::TextureHandle& rhs) { + return lhs.idx != rhs.idx; +} + namespace Impacto::Bgfx { -template +enum class VertexShaderType { + Sprite, +}; +enum class FragmentShaderType { + Sprite, +}; + +template +concept ShaderType = std::is_same_v || + std::is_same_v; + +template struct Uniforms; -template +template struct UniformHandles; -template +template class UniformsState { public: UniformsState() = delete; - UniformsState(bgfx::ProgramHandle program) : Program(program) { + UniformsState(bgfx::ProgramHandle program, std::function flush) + : Program(program), Flush(flush) { Submit(Uniforms{}); } - void Submit(const Uniforms& newUniforms); + void Submit(const Uniforms& newUniforms) { + constexpr static auto uniformNames = + boost::pfr::names_as_array>(); + constexpr static auto handleNames = + boost::pfr::names_as_array>(); + static_assert(uniformNames.size() == handleNames.size()); + + const auto updateUniform = [&] { + constexpr auto handleIt = + std::ranges::find(handleNames, uniformNames[UniformIdx]); + static_assert(handleIt != handleNames.end() && + "Uniform and UniformHandles struct need to share the same " + "member names"); + constexpr size_t handleIdx = std::distance(handleNames.begin(), handleIt); + + if (!CurrentUniforms.has_value() || + boost::pfr::get(*CurrentUniforms) != + boost::pfr::get(newUniforms)) { + if (CurrentUniforms.has_value()) Flush(); + + SetUniform(boost::pfr::get(Handles), + boost::pfr::get(newUniforms)); + } + }; + + [&](std::index_sequence) { + (updateUniform.template operator()(), ...); + }(std::make_index_sequence{}); + + CurrentUniforms = newUniforms; + } private: std::optional> CurrentUniforms; UniformHandles Handles; bgfx::ProgramHandle Program; + + std::function Flush; }; struct UniformHandle { @@ -35,7 +85,7 @@ struct UniformHandle { UniformHandle() = delete; UniformHandle(const UniformHandle&) = delete; UniformHandle(UniformHandle&& other) { *this = std::move(other); } - ~UniformHandle() { Reset(); } + virtual ~UniformHandle() { Reset(); } UniformHandle& operator=(const UniformHandle&) = delete; UniformHandle& operator=(UniformHandle&& other) { @@ -60,7 +110,7 @@ struct UniformHandle { } operator bgfx::UniformHandle() { return GetHandle(); } - private: + protected: bgfx::UniformHandle Handle = {bgfx::kInvalidHandle}; void Reset() { @@ -69,36 +119,16 @@ struct UniformHandle { } }; -template -void UniformsState::Submit(const Uniforms& newUniforms) { - constexpr static auto uniformNames = - boost::pfr::names_as_array>(); - constexpr static auto handleNames = - boost::pfr::names_as_array>(); - static_assert(uniformNames.size() == handleNames.size()); - - const auto updateUniform = [&] { - constexpr auto handleIt = - std::ranges::find(handleNames, uniformNames[UniformIdx]); - static_assert(handleIt != handleNames.end() && - "Uniform and UniformHandles struct need to share the same " - "member names"); - constexpr size_t handleIdx = std::distance(handleNames.begin(), handleIt); - - if (!CurrentUniforms.has_value() || - boost::pfr::get(*CurrentUniforms) != - boost::pfr::get(newUniforms)) { - SetUniform(boost::pfr::get(Handles), - boost::pfr::get(newUniforms)); - } - }; - - [&](std::index_sequence) { - (updateUniform.template operator()(), ...); - }(std::make_index_sequence{}); - - CurrentUniforms = newUniforms; -} +struct SamplerHandle final : public UniformHandle { + public: + SamplerHandle(const char* name, uint8_t stage) + : UniformHandle(name, bgfx::UniformType::Sampler, 1), Stage(stage) {} + + uint8_t GetStage() const { return Stage; } + + private: + uint8_t Stage; +}; template constexpr bgfx::UniformType::Enum GetUniformType(); @@ -138,12 +168,22 @@ inline void SetUniform(bgfx::UniformHandle handle, const float& value) { SetUniform(handle, glm::vec1(value)); } -#define DECLARE_UNIFORM_HANDLE(shaderProgramType, memberName, uniformName, \ - num) \ - UniformHandle memberName = UniformHandle( \ - #uniformName, \ - GetUniformType:: \ - memberName)>(), \ - num) +template <> +inline void SetUniform(bgfx::UniformHandle handle, + const bgfx::TextureHandle& value) { + bgfx::setTexture(0, handle, value); +} + +#define DECLARE_UNIFORM_HANDLE(shaderType, memberName, uniformName) \ + UniformHandle memberName = UniformHandle( \ + #uniformName, \ + GetUniformType::memberName)>()) + +#define DECLARE_SAMPLER_HANDLE(shaderType, memberName, uniformName, stage) \ + static_assert( \ + std::is_same_v::memberName)> && \ + "Sampler uniforms need to have uniform type bgfx::TextureHandle"); \ + SamplerHandle memberName = SamplerHandle(#uniformName, stage) } // namespace Impacto::Bgfx From 488e9f439c73c6e9c419248332b2931d60823c74 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 16:45:08 +0200 Subject: [PATCH 17/60] Remove depth buffer --- src/renderer/bgfx/framebuffer.cpp | 15 ++------------- src/renderer/bgfx/framebuffer.h | 1 - src/renderer/bgfx/renderer.cpp | 11 +++++++++++ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/renderer/bgfx/framebuffer.cpp b/src/renderer/bgfx/framebuffer.cpp index cae5eb58b..05371e7fd 100644 --- a/src/renderer/bgfx/framebuffer.cpp +++ b/src/renderer/bgfx/framebuffer.cpp @@ -12,7 +12,6 @@ FrameBuffer& FrameBuffer::operator=(FrameBuffer&& other) { FrameBufferHandle = other.FrameBufferHandle; ColorAttachment = other.ColorAttachment; - DepthStencilAttachment = other.DepthStencilAttachment; other.Reset(false); @@ -24,19 +23,10 @@ FrameBuffer::~FrameBuffer() { Reset(true); } FrameBuffer::FrameBuffer(const uint16_t width, const uint16_t height) : ColorAttachment(bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::RGBA8, - BGFX_TEXTURE_RT)), - DepthStencilAttachment(bgfx::createTexture2D(width, height, false, 1, - bgfx::TextureFormat::D24S8, - BGFX_TEXTURE_RT)) { + BGFX_TEXTURE_RT)) { assert(bgfx::isValid(ColorAttachment)); - assert(bgfx::isValid(DepthStencilAttachment)); - std::array attachments; - attachments[0].init(ColorAttachment); - attachments[1].init(DepthStencilAttachment); - - FrameBufferHandle = bgfx::createFrameBuffer( - static_cast(attachments.size()), attachments.data(), true); + FrameBufferHandle = bgfx::createFrameBuffer(1, &ColorAttachment, true); assert(bgfx::isValid(FrameBufferHandle)); } @@ -62,7 +52,6 @@ void FrameBuffer::Reset(bool cleanUpResources) { FrameBufferHandle.idx = bgfx::kInvalidHandle; ColorAttachment.idx = bgfx::kInvalidHandle; - DepthStencilAttachment.idx = bgfx::kInvalidHandle; } } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/framebuffer.h b/src/renderer/bgfx/framebuffer.h index b9e98fd3a..a3c864228 100644 --- a/src/renderer/bgfx/framebuffer.h +++ b/src/renderer/bgfx/framebuffer.h @@ -42,7 +42,6 @@ class FrameBuffer { private: bgfx::FrameBufferHandle FrameBufferHandle = {bgfx::kInvalidHandle}; bgfx::TextureHandle ColorAttachment = {bgfx::kInvalidHandle}; - bgfx::TextureHandle DepthStencilAttachment = {bgfx::kInvalidHandle}; void Reset(bool cleanUpResources); }; diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index cdca58b9b..d6ff0c58d 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -107,11 +107,22 @@ Renderer::Renderer() { BackBufferFrameBuffer = FrameBuffer::CreateBackBufferFrameBuffer(); + constexpr static glm::mat4 identityMatrix(1.0f); + bgfx::setViewTransform(DISPLAY_VIEW, glm::value_ptr(identityMatrix), + glm::value_ptr(identityMatrix)); + ViewMatrix = glm::mat4(1.0f); BackBufferProjectionMatrix = glm::ortho( 0.0f, static_cast(UserConfig::CommonSettings.ResolutionWidth), static_cast(UserConfig::CommonSettings.ResolutionHeight), 0.0f); + constexpr uint32_t black = 0x000000ff; + bgfx::setViewClear(DISPLAY_VIEW, BGFX_CLEAR_COLOR, black); + + constexpr uint32_t transparentWhite = 0xffffff00; + bgfx::setViewClear(RENDER_VIEW, BGFX_CLEAR_COLOR | BGFX_CLEAR_STENCIL, + transparentWhite); + Indices.resize(100); IndexBuffer = bgfx::createDynamicIndexBuffer( static_cast(Indices.size()), BGFX_BUFFER_ALLOW_RESIZE); From 650cb63efed91f590af038489f5f4d36ec8e8348 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 16:47:04 +0200 Subject: [PATCH 18/60] Remove backbuffer framebuffer --- src/renderer/bgfx/framebuffer.cpp | 15 --------------- src/renderer/bgfx/framebuffer.h | 2 -- src/renderer/bgfx/renderer.cpp | 6 ------ src/renderer/bgfx/renderer.h | 1 - 4 files changed, 24 deletions(-) diff --git a/src/renderer/bgfx/framebuffer.cpp b/src/renderer/bgfx/framebuffer.cpp index 05371e7fd..223abb0f5 100644 --- a/src/renderer/bgfx/framebuffer.cpp +++ b/src/renderer/bgfx/framebuffer.cpp @@ -30,21 +30,6 @@ FrameBuffer::FrameBuffer(const uint16_t width, const uint16_t height) assert(bgfx::isValid(FrameBufferHandle)); } -FrameBuffer FrameBuffer::CreateBackBufferFrameBuffer() { - FrameBuffer frameBuffer; - - frameBuffer.ColorAttachment = - bgfx::createTexture2D(bgfx::BackbufferRatio::Equal, false, 1, - bgfx::TextureFormat::RGBA8, BGFX_TEXTURE_RT); - assert(bgfx::isValid(frameBuffer.ColorAttachment)); - - frameBuffer.FrameBufferHandle = - bgfx::createFrameBuffer(1, &frameBuffer.ColorAttachment, true); - assert(bgfx::isValid(frameBuffer.FrameBufferHandle)); - - return frameBuffer; -} - void FrameBuffer::Reset(bool cleanUpResources) { if (cleanUpResources) { if (bgfx::isValid(FrameBufferHandle)) bgfx::destroy(FrameBufferHandle); diff --git a/src/renderer/bgfx/framebuffer.h b/src/renderer/bgfx/framebuffer.h index a3c864228..1a6aa3bae 100644 --- a/src/renderer/bgfx/framebuffer.h +++ b/src/renderer/bgfx/framebuffer.h @@ -20,8 +20,6 @@ class FrameBuffer { FrameBuffer(uint16_t width, uint16_t height); - [[nodiscard]] static FrameBuffer CreateBackBufferFrameBuffer(); - operator bgfx::FrameBufferHandle() { return GetFrameBufferHandle(); } [[nodiscard]] bgfx::FrameBufferHandle GetFrameBufferHandle() { diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index d6ff0c58d..fab53eafd 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -105,17 +105,11 @@ Renderer::Renderer() { Panic(LogChannel::Render, "Failed to initialize BGFX"); } - BackBufferFrameBuffer = FrameBuffer::CreateBackBufferFrameBuffer(); - constexpr static glm::mat4 identityMatrix(1.0f); bgfx::setViewTransform(DISPLAY_VIEW, glm::value_ptr(identityMatrix), glm::value_ptr(identityMatrix)); ViewMatrix = glm::mat4(1.0f); - BackBufferProjectionMatrix = glm::ortho( - 0.0f, static_cast(UserConfig::CommonSettings.ResolutionWidth), - static_cast(UserConfig::CommonSettings.ResolutionHeight), 0.0f); - constexpr uint32_t black = 0x000000ff; bgfx::setViewClear(DISPLAY_VIEW, BGFX_CLEAR_COLOR, black); diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index daa458686..9b68d659d 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -140,7 +140,6 @@ class Renderer final : public BaseRenderer { }; BgfxHandleStruct BgfxHandle; - FrameBuffer BackBufferFrameBuffer; FrameBuffer DrawFrameBuffer; bgfx::DynamicIndexBufferHandle IndexBuffer = {bgfx::kInvalidHandle}; From 16ff43ea0c3667f6fc84e0798c5a90df142e117d Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 16:48:17 +0200 Subject: [PATCH 19/60] Add command buffer --- src/renderer/bgfx/renderer.cpp | 164 +++++++++++++++++++++++++++------ src/renderer/bgfx/renderer.h | 22 ++++- 2 files changed, 154 insertions(+), 32 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index fab53eafd..1e50e0807 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -109,7 +109,6 @@ Renderer::Renderer() { bgfx::setViewTransform(DISPLAY_VIEW, glm::value_ptr(identityMatrix), glm::value_ptr(identityMatrix)); - ViewMatrix = glm::mat4(1.0f); constexpr uint32_t black = 0x000000ff; bgfx::setViewClear(DISPLAY_VIEW, BGFX_CLEAR_COLOR, black); @@ -117,9 +116,8 @@ Renderer::Renderer() { bgfx::setViewClear(RENDER_VIEW, BGFX_CLEAR_COLOR | BGFX_CLEAR_STENCIL, transparentWhite); - Indices.resize(100); - IndexBuffer = bgfx::createDynamicIndexBuffer( - static_cast(Indices.size()), BGFX_BUFFER_ALLOW_RESIZE); + IndexBuffer = bgfx::createDynamicIndexBuffer(static_cast(0), + BGFX_BUFFER_ALLOW_RESIZE); if (!bgfx::isValid(IndexBuffer)) { Panic(LogChannel::Render, "Failed to create index buffer"); } @@ -131,12 +129,9 @@ Renderer::Renderer() { .add(bgfx::Attrib::TexCoord1, 2, bgfx::AttribType::Float) .end(); - Vertices.resize(100); - VertexBuffer = bgfx::createDynamicVertexBuffer( - bgfx::copy( - Vertices.data(), - static_cast(Vertices.size() * sizeof(VertexBufferSprites))), - VertexBufferSpritesLayout); + VertexBuffer = bgfx::createDynamicVertexBuffer(static_cast(0), + VertexBufferSpritesLayout, + BGFX_BUFFER_ALLOW_RESIZE); if (!bgfx::isValid(VertexBuffer)) { Panic(LogChannel::Render, "Failed to create vertex buffer"); } @@ -188,9 +183,32 @@ void Renderer::Init() { FrameBuffer(static_cast(Profile::Game::DesignWidth), static_cast(Profile::Game::DesignHeight)); - ProjectionMatrix = + const glm::mat4 projectionMatrix = glm::ortho(0.0f, Profile::Game::DesignWidth, Profile::Game::DesignHeight, 0.0f, -Profile::Game::DesignWidth, Profile::Game::DesignWidth); + constexpr static glm::mat4 identityMatrix(1.0f); + bgfx::setViewTransform(RENDER_VIEW, glm::value_ptr(identityMatrix), + glm::value_ptr(projectionMatrix)); + + bgfx::setViewRect(RENDER_VIEW, 0, 0, + static_cast(Profile::Game::DesignWidth), + static_cast(Profile::Game::DesignHeight)); + + constexpr static std::array backBufferIndices = { + 0, 1, 3, 1, 2, 3, + }; + BackBufferIndexBuffer = bgfx::createIndexBuffer( + bgfx::copy(backBufferIndices.data(), sizeof(backBufferIndices))); + + constexpr static std::array backBufferVertices = { + VertexBufferSprites{.Position = {-1.0f, +1.0f}, .UV = {0.0f, 0.0f}}, + VertexBufferSprites{.Position = {-1.0f, -1.0f}, .UV = {0.0f, 1.0f}}, + VertexBufferSprites{.Position = {+1.0f, -1.0f}, .UV = {1.0f, 1.0f}}, + VertexBufferSprites{.Position = {+1.0f, +1.0f}, .UV = {1.0f, 0.0f}}, + }; + BackBufferVertexBuffer = bgfx::createVertexBuffer( + bgfx::copy(backBufferVertices.data(), sizeof(backBufferVertices)), + VertexBufferSpritesLayout); } RendererType Renderer::GetType() const { @@ -228,41 +246,39 @@ RendererType Renderer::GetType() const { Panic(LogChannel::Render, "Unexpected bgfx renderer \"{:s}\"\n", bgfx::getRendererName(bgfx::getRendererType())); - return RendererType{}; } void Renderer::BeginFrame() { bgfx::reset(static_cast(Window->WindowWidth), static_cast(Window->WindowHeight), BGFX_RESET_VSYNC); - constexpr uint32_t black = 0xff000000; - bgfx::setViewClear(DISPLAY_VIEW, BGFX_CLEAR_COLOR, black); bgfx::setViewRect(DISPLAY_VIEW, 0, 0, static_cast(Window->WindowWidth), static_cast(Window->WindowHeight)); - bgfx::setViewTransform(DISPLAY_VIEW, glm::value_ptr(ViewMatrix), - glm::value_ptr(BackBufferProjectionMatrix)); - bgfx::setViewFrameBuffer(DISPLAY_VIEW, BackBufferFrameBuffer); bgfx::touch(DISPLAY_VIEW); } void Renderer::BeginFrame2D() { - constexpr uint32_t transparentWhite = 0x00FFFFFF; - bgfx::setViewClear(RENDER_VIEW, - BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, - transparentWhite); - bgfx::setViewRect(RENDER_VIEW, 0, 0, - static_cast(Profile::Game::DesignWidth), - static_cast(Profile::Game::DesignHeight)); - bgfx::setViewTransform(RENDER_VIEW, glm::value_ptr(ViewMatrix), - glm::value_ptr(ProjectionMatrix)); bgfx::setViewFrameBuffer(RENDER_VIEW, DrawFrameBuffer); bgfx::touch(RENDER_VIEW); } -void Renderer::EndFrame() {} +void Renderer::EndFrame() { + Flush(); + + SetState({ + .ShaderProgram = *SpriteShader, + }); + + bgfx::setIndexBuffer(BackBufferIndexBuffer); + bgfx::setVertexBuffer(0, BackBufferVertexBuffer); + + SpriteShader->SubmitUniforms({}, {.Texture = DrawFrameBuffer.GetTexture()}); + + bgfx::submit(DISPLAY_VIEW, *SpriteShader); +} #ifndef IMPACTO_DISABLE_IMGUI void Renderer::ImGuiBeginFrame() { @@ -299,6 +315,16 @@ void Renderer::Shutdown() { if (bgfx::isValid(VertexBuffer)) bgfx::destroy(VertexBuffer); VertexBuffer.idx = bgfx::kInvalidHandle; + if (bgfx::isValid(BackBufferIndexBuffer)) { + bgfx::destroy(BackBufferIndexBuffer); + } + BackBufferIndexBuffer.idx = bgfx::kInvalidHandle; + + if (bgfx::isValid(BackBufferVertexBuffer)) { + bgfx::destroy(BackBufferVertexBuffer); + } + BackBufferVertexBuffer.idx = bgfx::kInvalidHandle; + #ifndef IMPACTO_DISABLE_IMGUI ImGui_ImplSDL3_Shutdown(); ImGui_Implbgfx_Shutdown(); @@ -306,4 +332,88 @@ void Renderer::Shutdown() { #endif } +void Renderer::Flush() { + assert(Indices.empty() == Vertices.empty()); + if (Indices.empty() || !CurrentState.has_value()) return; + + bgfx::update(IndexBuffer, 0, + bgfx::copy(Indices.data(), + static_cast(Indices.size() * + sizeof(Indices.front())))); + bgfx::update(VertexBuffer, 0, + bgfx::copy(Vertices.data(), + static_cast(Vertices.size() * + sizeof(Vertices.front())))); + + bgfx::setIndexBuffer(IndexBuffer); + bgfx::setVertexBuffer(0, VertexBuffer); + + bgfx::submit(RENDER_VIEW, CurrentState->ShaderProgram.get()); + + Indices.clear(); + Vertices.clear(); +} + +void Renderer::InsertVertices( + const std::span indices, + const std::span vertices) { + assert(indices.empty() == vertices.empty()); + if (indices.empty()) return; + + static uint16_t curIndex = 0; + if (Indices.empty()) curIndex = 0; + + Indices.resize(Indices.size() + indices.size()); + std::ranges::transform( + indices, Indices.begin() + (Indices.size() - indices.size()), + [&](const uint16_t index) { return index + curIndex; }); + curIndex += std::ranges::max(indices) + 1; + + Vertices.insert(Vertices.end(), vertices.begin(), vertices.end()); +} + +void Renderer::SetState(const CommandBuffer& newState) { + uint64_t stateFlags = + BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_ALWAYS; + bool differentStateFlags = !CurrentState.has_value(); + + if (!CurrentState.has_value() || + CurrentState->Transformation != newState.Transformation) { + Flush(); + bgfx::setTransform(glm::value_ptr(newState.Transformation)); + } + + if (CurrentState.has_value() && + &CurrentState->ShaderProgram.get() != &newState.ShaderProgram.get()) { + Flush(); + } + + if (!CurrentState.has_value() || + CurrentState->BlendMode != newState.BlendMode) { + Flush(); + differentStateFlags = true; + } + switch (newState.BlendMode) { + using enum RendererBlendMode; + case Normal: + stateFlags |= BGFX_STATE_BLEND_FUNC_SEPARATE( + BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA, + BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE); + break; + case Additive: + stateFlags |= BGFX_STATE_BLEND_FUNC_SEPARATE( + BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE, + BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE); + break; + case Premultiplied: + stateFlags |= BGFX_STATE_BLEND_NORMAL; + break; + } + + if (differentStateFlags) Flush(); + bgfx::setState(stateFlags); + + CurrentState = newState; +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 9b68d659d..dda7f0c7a 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -131,7 +131,10 @@ class Renderer final : public BaseRenderer { void Clear(glm::vec4 color) override {} private: - void Flush() override {} + void Flush() override; + + void InsertVertices(std::span indices, + std::span vertices); // Only call bgfx::shutdown after all managed objects in this class have been // default-destructed @@ -140,6 +143,16 @@ class Renderer final : public BaseRenderer { }; BgfxHandleStruct BgfxHandle; + struct CommandBuffer { + std::reference_wrapper ShaderProgram; + + glm::mat4 Transformation = glm::mat4(1.0f); + + RendererBlendMode BlendMode = RendererBlendMode::Normal; + }; + void SetState(const CommandBuffer& state); + std::optional CurrentState = std::nullopt; + FrameBuffer DrawFrameBuffer; bgfx::DynamicIndexBufferHandle IndexBuffer = {bgfx::kInvalidHandle}; @@ -147,11 +160,10 @@ class Renderer final : public BaseRenderer { std::vector Indices; std::vector Vertices; - bgfx::VertexLayout VertexBufferSpritesLayout; + bgfx::IndexBufferHandle BackBufferIndexBuffer = {bgfx::kInvalidHandle}; + bgfx::VertexBufferHandle BackBufferVertexBuffer = {bgfx::kInvalidHandle}; - glm::mat4 ViewMatrix; - glm::mat4 ProjectionMatrix; - glm::mat4 BackBufferProjectionMatrix; + bgfx::VertexLayout VertexBufferSpritesLayout; std::optional< ShaderProgram> From 344fad5c06601717feb48dba50b5e6aff6e656bf Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 16:48:38 +0200 Subject: [PATCH 20/60] Implement DrawSprite method --- src/renderer/bgfx/renderer.cpp | 51 ++++++++++++++++++++++++++++++++++ src/renderer/bgfx/renderer.h | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 1e50e0807..5bbe9e8db 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -416,4 +416,55 @@ void Renderer::SetState(const CommandBuffer& newState) { CurrentState = newState; } +void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, + const glm::mat4 transformation, + const std::span tints, + const glm::vec3 colorShift, const bool inverted, + const bool disableBlend, + const bool textureWrapRepeat) { + if (std::ranges::all_of( + tints, [](float alpha) { return alpha <= 0.0f; }, &glm::vec4::a)) { + return; + } + + SetState({ + .ShaderProgram = *SpriteShader, + .Transformation = transformation, + }); + + SpriteShader->SubmitUniforms({}, + { + .Texture = Textures[sprite.Sheet.Texture], + .ColorShift = colorShift, + }); + + const RectF normalizedBounds = sprite.NormalizedBounds(); + + constexpr static std::array indices = {0, 1, 3, 1, 2, 3}; + const std::array vertices = { + VertexBufferSprites{ + .Position = dest.TopLeft, + .UV = normalizedBounds.TopLeft(), + .Tint = tints[0], + }, + VertexBufferSprites{ + .Position = dest.BottomLeft, + .UV = normalizedBounds.BottomLeft(), + .Tint = tints[1], + }, + VertexBufferSprites{ + .Position = dest.BottomRight, + .UV = normalizedBounds.BottomRight(), + .Tint = tints[2], + }, + VertexBufferSprites{ + .Position = dest.TopRight, + .UV = normalizedBounds.TopRight(), + .Tint = tints[3], + }, + }; + + InsertVertices(indices, vertices); +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index dda7f0c7a..20b99815b 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -50,7 +50,7 @@ class Renderer final : public BaseRenderer { void DrawSprite(Sprite const& sprite, CornersQuad const& dest, glm::mat4 transformation, std::span tints, glm::vec3 colorShift, bool inverted, bool disableBlend, - bool textureWrapRepeat) override {} + bool textureWrapRepeat) override; void DrawMaskedSprite(Sprite const& sprite, Sprite const& mask, CornersQuad const& spriteDest, From d70d4e4efef2eb5b2a86d8cebedeaf0c5a2efee9 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 17:46:28 +0200 Subject: [PATCH 21/60] Initialize RectSprite --- src/renderer/bgfx/renderer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 5bbe9e8db..a10f6eb45 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -139,6 +139,11 @@ Renderer::Renderer() { const auto flush = [this]() { Flush(); }; SpriteShader.emplace(vs_sprite_shader, fs_sprite_shader, flush); + RectSprite = Sprite(SpriteSheet(1.0f, 1.0f), 0.0f, 0.0f, 1.0f, 1.0f); + RectSprite.Sheet.Texture = + SubmitTexture(TexFmt::TexFmt_RGBA, + std::array{0xFF, 0xFF, 0xFF, 0xFF}, 1, 1); + ImGui_Implbgfx_Init(IMGUI_VIEW); switch (UserConfig::AdvancedSettings.ActiveRenderer) { #ifdef IMPACTO_RENDERER_OPENGL From 20d71e634a395439591d64bc530a03f7e13b7b28 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 22:07:34 +0200 Subject: [PATCH 22/60] Only use one index/vertex buffer per frame --- src/renderer/bgfx/renderer.cpp | 46 ++++++++++++++++++++++------------ src/renderer/bgfx/renderer.h | 2 ++ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index a10f6eb45..f64b4e10f 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -273,6 +273,24 @@ void Renderer::BeginFrame2D() { void Renderer::EndFrame() { Flush(); + assert(Indices.empty() == Vertices.empty()); + if (!Indices.empty()) { + bgfx::update(IndexBuffer, 0, + bgfx::copy(Indices.data(), + static_cast(Indices.size() * + sizeof(Indices.front())))); + bgfx::update(VertexBuffer, 0, + bgfx::copy(Vertices.data(), + static_cast(Vertices.size() * + sizeof(Vertices.front())))); + + Indices.clear(); + Vertices.clear(); + + CurFrameIndexBufferOffset = 0; + CurFrameVertexBufferOffset = 0; + } + SetState({ .ShaderProgram = *SpriteShader, }); @@ -338,25 +356,21 @@ void Renderer::Shutdown() { } void Renderer::Flush() { - assert(Indices.empty() == Vertices.empty()); - if (Indices.empty() || !CurrentState.has_value()) return; + const bool empty = Indices.size() == CurFrameIndexBufferOffset; + assert(empty == (Vertices.size() == CurFrameVertexBufferOffset)); + if (empty || !CurrentState.has_value()) return; - bgfx::update(IndexBuffer, 0, - bgfx::copy(Indices.data(), - static_cast(Indices.size() * - sizeof(Indices.front())))); - bgfx::update(VertexBuffer, 0, - bgfx::copy(Vertices.data(), - static_cast(Vertices.size() * - sizeof(Vertices.front())))); + bgfx::setIndexBuffer( + IndexBuffer, static_cast(CurFrameIndexBufferOffset), + static_cast(Indices.size() - CurFrameIndexBufferOffset)); + bgfx::setVertexBuffer( + 0, VertexBuffer, static_cast(CurFrameVertexBufferOffset), + static_cast(Vertices.size() - CurFrameVertexBufferOffset)); - bgfx::setIndexBuffer(IndexBuffer); - bgfx::setVertexBuffer(0, VertexBuffer); + CurFrameIndexBufferOffset = Indices.size(); + CurFrameVertexBufferOffset = Vertices.size(); bgfx::submit(RENDER_VIEW, CurrentState->ShaderProgram.get()); - - Indices.clear(); - Vertices.clear(); } void Renderer::InsertVertices( @@ -366,7 +380,7 @@ void Renderer::InsertVertices( if (indices.empty()) return; static uint16_t curIndex = 0; - if (Indices.empty()) curIndex = 0; + if (Indices.size() == CurFrameIndexBufferOffset) curIndex = 0; Indices.resize(Indices.size() + indices.size()); std::ranges::transform( diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 20b99815b..1f92acc7f 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -159,6 +159,8 @@ class Renderer final : public BaseRenderer { bgfx::DynamicVertexBufferHandle VertexBuffer = {bgfx::kInvalidHandle}; std::vector Indices; std::vector Vertices; + size_t CurFrameIndexBufferOffset = 0; + size_t CurFrameVertexBufferOffset = 0; bgfx::IndexBufferHandle BackBufferIndexBuffer = {bgfx::kInvalidHandle}; bgfx::VertexBufferHandle BackBufferVertexBuffer = {bgfx::kInvalidHandle}; From 524818d171ea8ae518c1aee65939f9520ae80318 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Sun, 13 Sep 2026 22:53:14 +0200 Subject: [PATCH 23/60] Flip OpenGL buffers --- src/renderer/bgfx/renderer.cpp | 54 ++++++++++++++++++++++++++++++---- src/renderer/bgfx/renderer.h | 3 +- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index f64b4e10f..826c3e9c7 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -184,6 +184,8 @@ Renderer::Renderer() { } void Renderer::Init() { + [[maybe_unused]] const RendererType type = GetType(); + DrawFrameBuffer = FrameBuffer(static_cast(Profile::Game::DesignWidth), static_cast(Profile::Game::DesignHeight)); @@ -203,16 +205,35 @@ void Renderer::Init() { 0, 1, 3, 1, 2, 3, }; BackBufferIndexBuffer = bgfx::createIndexBuffer( - bgfx::copy(backBufferIndices.data(), sizeof(backBufferIndices))); + bgfx::makeRef(backBufferIndices.data(), sizeof(backBufferIndices))); + const bool shouldFlip = false +#ifdef IMPACTO_RENDERER_OPENGL + || type == RendererType::OpenGL +#endif +#ifdef IMPACTO_RENDERER_OPENGLES + || type == RendererType::OpenGLES +#endif + ; constexpr static std::array backBufferVertices = { VertexBufferSprites{.Position = {-1.0f, +1.0f}, .UV = {0.0f, 0.0f}}, VertexBufferSprites{.Position = {-1.0f, -1.0f}, .UV = {0.0f, 1.0f}}, VertexBufferSprites{.Position = {+1.0f, -1.0f}, .UV = {1.0f, 1.0f}}, VertexBufferSprites{.Position = {+1.0f, +1.0f}, .UV = {1.0f, 0.0f}}, }; + constexpr static std::array + flippedBackBufferVertices = { + VertexBufferSprites{.Position = {-1.0f, -1.0f}, .UV = {0.0f, 0.0f}}, + VertexBufferSprites{.Position = {-1.0f, +1.0f}, .UV = {0.0f, 1.0f}}, + VertexBufferSprites{.Position = {+1.0f, +1.0f}, .UV = {1.0f, 1.0f}}, + VertexBufferSprites{.Position = {+1.0f, -1.0f}, .UV = {1.0f, 0.0f}}, + }; + const std::span correctBackBufferVertices = + shouldFlip ? flippedBackBufferVertices : backBufferVertices; BackBufferVertexBuffer = bgfx::createVertexBuffer( - bgfx::copy(backBufferVertices.data(), sizeof(backBufferVertices)), + bgfx::makeRef( + correctBackBufferVertices.data(), + static_cast(correctBackBufferVertices.size_bytes())), VertexBufferSpritesLayout); } @@ -373,9 +394,22 @@ void Renderer::Flush() { bgfx::submit(RENDER_VIEW, CurrentState->ShaderProgram.get()); } +static bool ShouldFlip(const Sprite& sprite) { + [[maybe_unused]] const RendererType rendererType = + Impacto::Renderer->GetType(); + return sprite.Sheet.IsScreenCap && (false +#ifdef IMPACTO_RENDERER_OPENGL + || rendererType == RendererType::OpenGL +#endif +#ifdef IMPACTO_RENDERER_OPENGLES + || rendererType == RendererType::OpenGLES +#endif + ); +} + void Renderer::InsertVertices( const std::span indices, - const std::span vertices) { + const std::span vertices, bool flipVertically) { assert(indices.empty() == vertices.empty()); if (indices.empty()) return; @@ -388,7 +422,17 @@ void Renderer::InsertVertices( [&](const uint16_t index) { return index + curIndex; }); curIndex += std::ranges::max(indices) + 1; - Vertices.insert(Vertices.end(), vertices.begin(), vertices.end()); + if (!flipVertically) { + Vertices.insert(Vertices.end(), vertices.begin(), vertices.end()); + } else { + Vertices.resize(Vertices.size() + vertices.size()); + std::ranges::transform( + vertices, Vertices.begin() + (Vertices.size() - vertices.size()), + [](VertexBufferSprites vertex) { + vertex.Position.y = Profile::Game::DesignHeight - vertex.Position.y; + return vertex; + }); + } } void Renderer::SetState(const CommandBuffer& newState) { @@ -483,7 +527,7 @@ void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, }, }; - InsertVertices(indices, vertices); + InsertVertices(indices, vertices, ShouldFlip(sprite)); } } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 1f92acc7f..e4f3bf256 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -134,7 +134,8 @@ class Renderer final : public BaseRenderer { void Flush() override; void InsertVertices(std::span indices, - std::span vertices); + std::span vertices, + bool flipVertically); // Only call bgfx::shutdown after all managed objects in this class have been // default-destructed From 9df5a8b608218a45bdd6f98b06629c8b857791a6 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 15 Sep 2026 02:12:23 +0200 Subject: [PATCH 24/60] Get uniform handles from bgfx's embedded shaders directly --- src/renderer/bgfx/renderer.cpp | 6 +- src/renderer/bgfx/shader.h | 4 +- src/renderer/bgfx/shaders/fs_sprite.h | 10 +- src/renderer/bgfx/shaders/vs_sprite.h | 3 - src/renderer/bgfx/uniform.h | 236 ++++++++++++-------------- 5 files changed, 115 insertions(+), 144 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 826c3e9c7..df81e40d8 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -319,7 +319,7 @@ void Renderer::EndFrame() { bgfx::setIndexBuffer(BackBufferIndexBuffer); bgfx::setVertexBuffer(0, BackBufferVertexBuffer); - SpriteShader->SubmitUniforms({}, {.Texture = DrawFrameBuffer.GetTexture()}); + SpriteShader->SubmitUniforms({}, {.s_texture = DrawFrameBuffer.GetTexture()}); bgfx::submit(DISPLAY_VIEW, *SpriteShader); } @@ -497,8 +497,8 @@ void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, SpriteShader->SubmitUniforms({}, { - .Texture = Textures[sprite.Sheet.Texture], - .ColorShift = colorShift, + .s_texture = Textures[sprite.Sheet.Texture], + .u_colorShift = colorShift, }); const RectF normalizedBounds = sprite.NormalizedBounds(); diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h index aabf60be5..81a80beda 100644 --- a/src/renderer/bgfx/shader.h +++ b/src/renderer/bgfx/shader.h @@ -105,8 +105,8 @@ ShaderProgram::ShaderProgram( ProgramHandle = bgfx::createProgram(VertexShader, FragmentShader, true); assert(bgfx::isValid(ProgramHandle)); - VertexUniformsState.emplace(ProgramHandle, flush); - FragmentUniformsState.emplace(ProgramHandle, flush); + VertexUniformsState.emplace(VertexShader, flush); + FragmentUniformsState.emplace(FragmentShader, flush); } template struct Uniforms { - bgfx::TextureHandle Texture = {bgfx::kInvalidHandle}; - glm::vec3 ColorShift = glm::vec3(0.0f); -}; - -template <> -struct UniformHandles { - DECLARE_SAMPLER_HANDLE(FragmentShaderType::Sprite, Texture, s_texture, 0); - DECLARE_UNIFORM_HANDLE(FragmentShaderType::Sprite, ColorShift, u_colorShift); + bgfx::TextureHandle s_texture = {bgfx::kInvalidHandle}; + glm::vec3 u_colorShift = glm::vec3(0.0f); }; } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shaders/vs_sprite.h b/src/renderer/bgfx/shaders/vs_sprite.h index b27bb36c4..cf4aa5b2f 100644 --- a/src/renderer/bgfx/shaders/vs_sprite.h +++ b/src/renderer/bgfx/shaders/vs_sprite.h @@ -7,7 +7,4 @@ namespace Impacto::Bgfx { template <> struct Uniforms {}; -template <> -struct UniformHandles {}; - } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h index 934fb615c..3e8e37b2a 100644 --- a/src/renderer/bgfx/uniform.h +++ b/src/renderer/bgfx/uniform.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "../renderer.h" @@ -13,123 +14,6 @@ inline bool operator!=(const bgfx::TextureHandle& lhs, namespace Impacto::Bgfx { -enum class VertexShaderType { - Sprite, -}; -enum class FragmentShaderType { - Sprite, -}; - -template -concept ShaderType = std::is_same_v || - std::is_same_v; - -template -struct Uniforms; - -template -struct UniformHandles; - -template -class UniformsState { - public: - UniformsState() = delete; - UniformsState(bgfx::ProgramHandle program, std::function flush) - : Program(program), Flush(flush) { - Submit(Uniforms{}); - } - - void Submit(const Uniforms& newUniforms) { - constexpr static auto uniformNames = - boost::pfr::names_as_array>(); - constexpr static auto handleNames = - boost::pfr::names_as_array>(); - static_assert(uniformNames.size() == handleNames.size()); - - const auto updateUniform = [&] { - constexpr auto handleIt = - std::ranges::find(handleNames, uniformNames[UniformIdx]); - static_assert(handleIt != handleNames.end() && - "Uniform and UniformHandles struct need to share the same " - "member names"); - constexpr size_t handleIdx = std::distance(handleNames.begin(), handleIt); - - if (!CurrentUniforms.has_value() || - boost::pfr::get(*CurrentUniforms) != - boost::pfr::get(newUniforms)) { - if (CurrentUniforms.has_value()) Flush(); - - SetUniform(boost::pfr::get(Handles), - boost::pfr::get(newUniforms)); - } - }; - - [&](std::index_sequence) { - (updateUniform.template operator()(), ...); - }(std::make_index_sequence{}); - - CurrentUniforms = newUniforms; - } - - private: - std::optional> CurrentUniforms; - UniformHandles Handles; - - bgfx::ProgramHandle Program; - - std::function Flush; -}; - -struct UniformHandle { - public: - UniformHandle() = delete; - UniformHandle(const UniformHandle&) = delete; - UniformHandle(UniformHandle&& other) { *this = std::move(other); } - virtual ~UniformHandle() { Reset(); } - - UniformHandle& operator=(const UniformHandle&) = delete; - UniformHandle& operator=(UniformHandle&& other) { - if (this == &other) return *this; - Reset(); - - Handle = other.Handle; - other.Handle.idx = bgfx::kInvalidHandle; - - return *this; - } - - UniformHandle(const char* name, bgfx::UniformType::Enum type, - uint16_t num = 1) - : Handle(bgfx::createUniform(name, type, num)) { - assert(bgfx::isValid(Handle)); - } - - bgfx::UniformHandle GetHandle() { - assert(bgfx::isValid(Handle)); - return Handle; - } - operator bgfx::UniformHandle() { return GetHandle(); } - - protected: - bgfx::UniformHandle Handle = {bgfx::kInvalidHandle}; - - void Reset() { - if (bgfx::isValid(Handle)) bgfx::destroy(Handle); - Handle.idx = bgfx::kInvalidHandle; - } -}; - -struct SamplerHandle final : public UniformHandle { - public: - SamplerHandle(const char* name, uint8_t stage) - : UniformHandle(name, bgfx::UniformType::Sampler, 1), Stage(stage) {} - - uint8_t GetStage() const { return Stage; } - - private: - uint8_t Stage; -}; - template constexpr bgfx::UniformType::Enum GetUniformType(); @@ -141,6 +25,11 @@ constexpr bgfx::UniformType::Enum GetUniformType() { return bgfx::UniformType::Vec4; } +template <> +constexpr bgfx::UniformType::Enum GetUniformType() { + return bgfx::UniformType::Sampler; +} + template void SetUniform(bgfx::UniformHandle handle, const T& value); @@ -171,19 +60,110 @@ inline void SetUniform(bgfx::UniformHandle handle, const float& value) { template <> inline void SetUniform(bgfx::UniformHandle handle, const bgfx::TextureHandle& value) { + static_assert(GetUniformType>() == + bgfx::UniformType::Sampler); + bgfx::setTexture(0, handle, value); } -#define DECLARE_UNIFORM_HANDLE(shaderType, memberName, uniformName) \ - UniformHandle memberName = UniformHandle( \ - #uniformName, \ - GetUniformType::memberName)>()) - -#define DECLARE_SAMPLER_HANDLE(shaderType, memberName, uniformName, stage) \ - static_assert( \ - std::is_same_v::memberName)> && \ - "Sampler uniforms need to have uniform type bgfx::TextureHandle"); \ - SamplerHandle memberName = SamplerHandle(#uniformName, stage) +enum class VertexShaderType { + Sprite, +}; +enum class FragmentShaderType { + Sprite, +}; + +template +concept ShaderType = std::is_same_v || + std::is_same_v; + +template +struct Uniforms; + +template +class UniformsState { + public: + UniformsState() = delete; + UniformsState(bgfx::ShaderHandle shader, std::function flush) + : Flush(flush) { + const uint16_t internalUniformCount = + bgfx::getShaderUniforms(shader, nullptr, 0); + std::vector unorderedHandles(internalUniformCount); + bgfx::getShaderUniforms(shader, unorderedHandles.data(), + static_cast(unorderedHandles.size())); + + // Some backends declare the same uniform multiple times, for some reason + // Only count unique handles + std::set uniqueHandles; + std::ranges::transform(unorderedHandles, + std::inserter(uniqueHandles, uniqueHandles.end()), + &bgfx::UniformHandle::idx); + assert(uniqueHandles.size() == UniformCount && + "The number of uniforms defined in shader code is not equal to the " + "number of uniforms defined in the struct. (Some types in the " + "shader code may be illegal!)"); + + constexpr static auto uniformNames = + boost::pfr::names_as_array>(); + [[maybe_unused]] constexpr static auto uniformTypes = [&]() { + std::array types; + + const auto getType = [&] { + types[UniformIdx] = GetUniformType( + Uniforms{}))>(); + }; + + [&](std::index_sequence) { + (getType.template operator()(), ...); + }(std::make_index_sequence{}); + + return types; + }(); + + for (decltype(bgfx::UniformHandle::idx) handle : uniqueHandles) { + bgfx::UniformInfo info; + bgfx::getUniformInfo({handle}, info); + + const auto uniformIt = std::ranges::find(uniformNames, info.name); + assert(uniformIt != uniformNames.end() && + "Uniforms struct needs to share the same uniform names as " + "the shader source code"); + const size_t uniformIdx = std::distance(uniformNames.begin(), uniformIt); + + assert(info.type == uniformTypes[uniformIdx] && + "A uniform's struct type cannot be converted to its shader type"); + + Handles[uniformIdx] = {handle}; + } + + Submit(Uniforms{}); + } + + void Submit(const Uniforms& newUniforms) { + const auto updateUniform = [&] { + if (CurrentUniforms.has_value() && + boost::pfr::get(*CurrentUniforms) != + boost::pfr::get(newUniforms)) { + Flush(); + } + SetUniform(Handles[UniformIdx], boost::pfr::get(newUniforms)); + }; + + [&](std::index_sequence) { + (updateUniform.template operator()(), ...); + }(std::make_index_sequence{}); + + CurrentUniforms = newUniforms; + } + + private: + constexpr static size_t UniformCount = + boost::pfr::names_as_array>().size(); + + std::optional> CurrentUniforms; + std::array Handles; + + std::function Flush; +}; } // namespace Impacto::Bgfx From 3f66cf899fd2ab8c7d3b886efb4504b7602eff24 Mon Sep 17 00:00:00 2001 From: Dextinfire <> Date: Tue, 15 Sep 2026 03:35:58 -0700 Subject: [PATCH 25/60] Fix bgfx switch build --- CMakeLists.txt | 3 +- HorizonNX.toolchain | 2 +- doc/switch_build.md | 1 + portfiles-switch/bgfx/fix-dependencies.patch | 420 +++++++++++++++++++ portfiles-switch/bgfx/portfile.cmake | 81 ++++ portfiles-switch/bgfx/switch.patch | 224 ++++++++++ portfiles-switch/bgfx/vcpkg.json | 55 +++ src/renderer/bgfx/renderer.cpp | 7 + src/renderer/bgfx/uniform.h | 3 +- src/renderer/renderer.h | 4 +- 10 files changed, 794 insertions(+), 6 deletions(-) create mode 100644 portfiles-switch/bgfx/fix-dependencies.patch create mode 100644 portfiles-switch/bgfx/portfile.cmake create mode 100644 portfiles-switch/bgfx/switch.patch create mode 100644 portfiles-switch/bgfx/vcpkg.json diff --git a/CMakeLists.txt b/CMakeLists.txt index e7400c078..ca9a84fce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -841,7 +841,8 @@ elseif (ANDROID) set(IMPACTO_RENDERER_VULKAN ON) set(IMPACTO_RENDERER_OPENGLES ON) elseif (NX) - set(IMPACTO_RENDERER_VULKAN ON) + set(IMPACTO_RENDERER_VULKAN OFF) + set(IMPACTO_RENDERER_OPENGLES ON) else () message(FATAL_ERROR "No renderer backends supplied for target platform") endif () diff --git a/HorizonNX.toolchain b/HorizonNX.toolchain index 65bc4e76d..60ae89e50 100644 --- a/HorizonNX.toolchain +++ b/HorizonNX.toolchain @@ -32,7 +32,7 @@ set(ENV{PKG_CONFIG_PATH} "") set(ENV{PKG_CONFIG_LIBDIR} "${DEVKITPRO}/portlibs/switch/lib/pkgconfig") set(ENV{PKG_CONFIG_SYSROOT_DIR} "${DEVKITPRO}/portlibs/switch") -set(CMAKE_C_FLAGS_INIT "${CPPFLAGS} -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIC -ffunction-sections -D__SWITCH__ -I${DEVKITPRO}/libnx/include -ftls-model=local-exec" CACHE STRING "C flags") +set(CMAKE_C_FLAGS_INIT "${CPPFLAGS} -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIC -ffunction-sections -D__NX__ -D__SWITCH__ -I${DEVKITPRO}/libnx/include -ftls-model=local-exec -D_DEFAULT_SOURCE" CACHE STRING "C flags") set(CMAKE_CXX_FLAGS_INIT "${CPPFLAGS} ${CMAKE_C_FLAGS_INIT}" CACHE STRING "C++ flags") if(WITH_PORTLIBS) diff --git a/doc/switch_build.md b/doc/switch_build.md index a4731253d..fd1c832c1 100644 --- a/doc/switch_build.md +++ b/doc/switch_build.md @@ -19,6 +19,7 @@ the same `find_package(... CONFIG)` interface and imported targets on every plat (e.g. `/opt/devkitpro`). * A **vcpkg** checkout, with the `VCPKG_ROOT` environment variable pointing at it. * **CMake** ≥ 3.31 and **Ninja**. +* Additional host dependencies may be needed, see [`Switch Dockerfile`](../docker/impacto-switch/Dockerfile) for an always up-to-date version ## Building diff --git a/portfiles-switch/bgfx/fix-dependencies.patch b/portfiles-switch/bgfx/fix-dependencies.patch new file mode 100644 index 000000000..88d7b4758 --- /dev/null +++ b/portfiles-switch/bgfx/fix-dependencies.patch @@ -0,0 +1,420 @@ +diff --git a/bgfx/examples/common/bgfx_utils.cpp b/bgfx/examples/common/bgfx_utils.cpp +index baaeba3..f6bc854 100644 +--- a/bgfx/examples/common/bgfx_utils.cpp ++++ b/bgfx/examples/common/bgfx_utils.cpp +@@ -17,7 +17,7 @@ namespace stl = tinystl; + #include + #include + #include "entry/entry.h" +-#include ++#include + + #include "bgfx_utils.h" + +diff --git a/bgfx/examples/common/font/font_manager.cpp b/bgfx/examples/common/font/font_manager.cpp +index 92e497a..85d1495 100644 +--- a/bgfx/examples/common/font/font_manager.cpp ++++ b/bgfx/examples/common/font/font_manager.cpp +@@ -4,7 +4,7 @@ + */ + + #include +-#include ++#include + #include "../common.h" + #include + +diff --git a/bgfx/examples/common/imgui/imgui.cpp b/bgfx/examples/common/imgui/imgui.cpp +index 2fe8258..1006741 100644 +--- a/bgfx/examples/common/imgui/imgui.cpp ++++ b/bgfx/examples/common/imgui/imgui.cpp +@@ -8,10 +8,10 @@ + #include + #include + #include +-#include +-#include ++#include ++#include + +-#include "imgui.h" ++#include "imgui/imgui.h" + #include "../bgfx_utils.h" + + #ifndef USE_ENTRY +@@ -591,7 +591,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wtype-limits"); // warning: comparison + # define STBTT_free(_ptr, _userData) memFree(_ptr, _userData) + + # define STB_RECT_PACK_IMPLEMENTATION +-# include ++# include + # define STB_TRUETYPE_IMPLEMENTATION +-# include ++# include + #endif // USE_LOCAL_STB +diff --git a/bgfx/examples/common/imgui/imgui.h b/bgfx/examples/common/imgui/imgui.h +index 865879e..c6a3d84 100644 +--- a/bgfx/examples/common/imgui/imgui.h ++++ b/bgfx/examples/common/imgui/imgui.h +@@ -7,7 +7,7 @@ + #define IMGUI_H_HEADER_GUARD + + #include +-#include ++#include + #include + #include + +diff --git a/bgfx/examples/common/nanovg/fontstash.h b/bgfx/examples/common/nanovg/fontstash.h +index 39a48fb..ca0056d 100644 +--- a/bgfx/examples/common/nanovg/fontstash.h ++++ b/bgfx/examples/common/nanovg/fontstash.h +@@ -266,7 +266,7 @@ static void fons__tmpfree(void* ptr, void* up); + #endif // 0 + + #define STBTT_DEF extern +-#include ++#include + + struct FONSttFontImpl { + stbtt_fontinfo font; +diff --git a/bgfx/tools/geometryc/geometryc.cpp b/bgfx/tools/geometryc/geometryc.cpp +index d79a80e..7740272 100644 +--- a/bgfx/tools/geometryc/geometryc.cpp ++++ b/bgfx/tools/geometryc/geometryc.cpp +@@ -14,11 +14,11 @@ + #include + namespace stl = tinystl; + +-#include ++#include + + #define CGLTF_VALIDATE_ENABLE_ASSERTS BX_CONFIG_DEBUG + #define CGLTF_IMPLEMENTATION +-#include ++#include + + #define BGFX_GEOMETRYC_VERSION_MAJOR 1 + #define BGFX_GEOMETRYC_VERSION_MINOR 0 +diff --git a/bgfx/tools/shaderc/shaderc_metal.cpp b/bgfx/tools/shaderc/shaderc_metal.cpp +index 9f073b9..e8fd208 100644 +--- a/bgfx/tools/shaderc/shaderc_metal.cpp ++++ b/bgfx/tools/shaderc/shaderc_metal.cpp +@@ -20,11 +20,10 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u + #include + + #define ENABLE_OPT 1 +-#include +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include + #include + BX_PRAGMA_DIAGNOSTIC_POP() + +diff --git a/bgfx/tools/shaderc/shaderc_spirv.cpp b/bgfx/tools/shaderc/shaderc_spirv.cpp +index f7910de..a844cc0 100644 +--- a/bgfx/tools/shaderc/shaderc_spirv.cpp ++++ b/bgfx/tools/shaderc/shaderc_spirv.cpp +@@ -20,11 +20,10 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u + #include + + #define ENABLE_OPT 1 +-#include +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include + #include + BX_PRAGMA_DIAGNOSTIC_POP() + +diff --git a/bimg/src/image_decode.cpp b/bimg/src/image_decode.cpp +index 798eaba..a4cd3ef 100644 +--- a/bimg/src/image_decode.cpp ++++ b/bimg/src/image_decode.cpp +@@ -16,22 +16,14 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4018) // warning C4018: '<': signed/unsigned + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // error C4100: '' : unreferenced formal parameter + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4389) // warning C4389 : '==' : signed / unsigned mismatch + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505) // warning C4505: 'tinyexr::miniz::def_realloc_func': unreferenced local function has been removed +-#define MINIZ_NO_ARCHIVE_APIS +-#define MINIZ_NO_STDIO +-#define TINYEXR_IMPLEMENTATION +-#include ++#include + BX_PRAGMA_DIAGNOSTIC_POP() + + BX_PRAGMA_DIAGNOSTIC_PUSH(); + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4127) // warning C4127: conditional expression is constant + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4267) // warning C4267: '=' : conversion from 'size_t' to 'unsigned short', possible loss of data + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4334) // warning C4334: '<<' : result of 32 - bit shift implicitly converted to 64 bits(was 64 - bit shift intended ? ) +-#define LODEPNG_NO_COMPILE_ENCODER +-#define LODEPNG_NO_COMPILE_DISK +-#define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS +-#define LODEPNG_NO_COMPILE_ALLOCATORS +-#define LODEPNG_NO_COMPILE_CPP +-#include ++#include + BX_PRAGMA_DIAGNOSTIC_POP(); + + #if BIMG_DECODE_HEIF +@@ -72,7 +64,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wimplicit-fallthrough"); + #define STBI_FREE(_ptr) lodepng_free(_ptr) + #define STB_IMAGE_IMPLEMENTATION + #define STB_IMAGE_STATIC +-#include ++#include + BX_PRAGMA_DIAGNOSTIC_POP(); + + namespace bimg +@@ -453,7 +445,7 @@ namespace bimg + case TINYEXR_ERROR_INVALID_HEADER: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Invalid header."); break; + case TINYEXR_ERROR_UNSUPPORTED_FEATURE: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Unsupported feature."); break; + case TINYEXR_ERROR_CANT_WRITE_FILE: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Can't write file."); break; +- case TINYEXR_ERROR_SERIALZATION_FAILED: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Serialization failed."); break; ++ case TINYEXR_ERROR_SERIALIZATION_FAILED: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image. Serialization failed."); break; + default: BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Failed to parse image."); break; + } + } +diff --git a/bimg/src/image_encode.cpp b/bimg/src/image_encode.cpp +index 7c0cd76..530578f 100644 +--- a/bimg/src/image_encode.cpp ++++ b/bimg/src/image_encode.cpp +@@ -6,7 +6,7 @@ + #include + #include "bimg_p.h" + +-#include ++#include + #include + #include + #include +@@ -19,7 +19,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // warning C4100: 'alloc_context': unref + BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4702) // warning C4702: unreachable code + BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-parameter") // warning: unused parameter ‘alloc_context’ [-Wunused-parameter] + #define STB_IMAGE_RESIZE_IMPLEMENTATION +-#include ++#include + BX_PRAGMA_DIAGNOSTIC_POP(); + + extern "C" { +@@ -564,18 +564,16 @@ namespace bimg + const uint32_t srcDataStep = uint32_t(bx::floor(zz * _src->m_depth / float(_dst->m_depth) ) ); + const uint8_t* srcData = &srcMip.m_data[srcDataStep*srcSlice]; + +- int result = stbir_resize_float_generic( +- (const float*)srcData, _src->m_width, _src->m_height, srcPitch +- , ( float*)dstData, _dst->m_width, _dst->m_height, dstPitch +- , 4, 3 +- , STBIR_FLAG_ALPHA_PREMULTIPLIED ++ void* result = stbir_resize( ++ (const void *)srcData, _src->m_width, _src->m_height, srcPitch ++ , ( void *)dstData, _dst->m_width, _dst->m_height, dstPitch ++ , STBIR_RGBA_PM ++ , STBIR_TYPE_FLOAT + , STBIR_EDGE_CLAMP + , STBIR_FILTER_BOX +- , STBIR_COLORSPACE_LINEAR +- , NULL + ); + +- if (1 != result) ++ if (0 == result) + { + return false; + } +diff --git a/bx/src/settings.cpp b/bx/src/settings.cpp +index 907c74c..ffcc442 100644 +--- a/bx/src/settings.cpp ++++ b/bx/src/settings.cpp +@@ -19,7 +19,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-function"); + + BX_PRAGMA_DIAGNOSTIC_PUSH(); + BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wsign-compare"); +-#include ++#include + BX_PRAGMA_DIAGNOSTIC_POP(); + } + +@@ -58,7 +58,7 @@ void Settings::load(const void* _data, uint32_t _len) + } + else + { +- m_ini = ini_load( (const char*)_data, _len, m_allocator); ++ m_ini = ini_load( (const char*)_data, m_allocator); + } + } + +diff --git a/cmake/Config.cmake.in b/cmake/Config.cmake.in +index 33a3943..8eddd3f 100644 +--- a/cmake/Config.cmake.in ++++ b/cmake/Config.cmake.in +@@ -1,5 +1,22 @@ + @PACKAGE_INIT@ + ++include(CMakeFindDependencyMacro) ++find_dependency(lodepng CONFIG) ++find_dependency(miniz CONFIG) ++find_dependency(tinyexr CONFIG) ++find_dependency(unofficial-libsquish CONFIG) ++if("@BGFX_BUILD_TOOLS_GEOMETRY@") ++ find_dependency(meshoptimizer CONFIG) ++endif() ++if("@BGFX_BUILD_TOOLS_SHADER@") ++ find_dependency(spirv_cross_core CONFIG) ++ find_dependency(spirv_cross_reflect CONFIG) ++ find_dependency(spirv_cross_glsl CONFIG) ++ find_dependency(spirv_cross_hlsl CONFIG) ++ find_dependency(spirv_cross_msl CONFIG) ++ find_dependency(glslang CONFIG REQUIRED) ++endif() ++ + if(@BGFX_CMAKE_USER_SCRIPT_PRESENT@) + include("${CMAKE_CURRENT_LIST_DIR}/@BGFX_CMAKE_USER_SCRIPT_INSTALL_NAME@") + endif() +diff --git a/cmake/bgfx/CMakeLists.txt b/cmake/bgfx/CMakeLists.txt +index 0125da3..9b10d09 100644 +--- a/cmake/bgfx/CMakeLists.txt ++++ b/cmake/bgfx/CMakeLists.txt +@@ -9,20 +9,22 @@ + # this software. If not, see . + + include(bgfx.cmake) +-include(3rdparty/meshoptimizer.cmake) +-include(3rdparty/dear-imgui.cmake) + + if(BGFX_BUILD_TOOLS_TEXTURE) +- include(texturev.cmake) + endif() + if(BGFX_BUILD_TOOLS_GEOMETRY) ++ find_package(meshoptimizer CONFIG REQUIRED) ++ set(MESHOPTIMIZER_LIBRARIES "meshoptimizer::meshoptimizer" CACHE INTERNAL "") + include(geometryc.cmake) +- include(geometryv.cmake) + endif() + if(BGFX_BUILD_TOOLS_SHADER) +- include(3rdparty/spirv-opt.cmake) +- include(3rdparty/spirv-cross.cmake) +- include(3rdparty/glslang.cmake) ++ find_package(spirv_cross_core CONFIG REQUIRED) ++ find_package(spirv_cross_reflect CONFIG REQUIRED) ++ find_package(spirv_cross_glsl CONFIG REQUIRED) ++ find_package(spirv_cross_hlsl CONFIG REQUIRED) ++ find_package(spirv_cross_msl CONFIG REQUIRED) ++ find_package(glslang CONFIG REQUIRED) ++ + include(3rdparty/glsl-optimizer.cmake) + include(3rdparty/fcpp.cmake) + include(3rdparty/webgpu.cmake) +diff --git a/cmake/bgfx/shaderc.cmake b/cmake/bgfx/shaderc.cmake +index 0f50eab..8b13b28 100644 +--- a/cmake/bgfx/shaderc.cmake ++++ b/cmake/bgfx/shaderc.cmake +@@ -24,21 +24,10 @@ target_link_libraries( + PRIVATE bx + bgfx-vertexlayout + fcpp +- glslang +- glsl-optimizer +- spirv-opt +- spirv-cross +-) +-target_link_libraries( +- shaderc +- PRIVATE bx + bimg +- bgfx-vertexlayout +- fcpp +- glslang ++ glslang::glslang glslang::glslang-default-resource-limits glslang::SPIRV + glsl-optimizer +- spirv-opt +- spirv-cross ++ spirv-cross-core spirv-cross-reflect spirv-cross-glsl spirv-cross-hlsl spirv-cross-msl + webgpu + ) + if(BGFX_AMALGAMATED) +diff --git a/cmake/bimg/CMakeLists.txt b/cmake/bimg/CMakeLists.txt +index 200b29b..1c857c0 100644 +--- a/cmake/bimg/CMakeLists.txt ++++ b/cmake/bimg/CMakeLists.txt +@@ -8,17 +8,24 @@ + # You should have received a copy of the CC0 Public Domain Dedication along with + # this software. If not, see . + +-include(3rdparty/loadpng.cmake) +-include(3rdparty/libsquish.cmake) ++find_package(lodepng CONFIG REQUIRED) ++set(LOADPNG_LIBRARIES "$;$>") ++find_package(unofficial-libsquish CONFIG REQUIRED) ++set(LIBSQUISH_LIBRARIES "$;$>") + include(3rdparty/astc_encoder.cmake) + include(3rdparty/edtaa3.cmake) + include(3rdparty/etc1.cmake) + include(3rdparty/etc2.cmake) + include(3rdparty/nvtt.cmake) + include(3rdparty/pvrtc.cmake) +-include(3rdparty/tinyexr.cmake) ++find_package(tinyexr CONFIG REQUIRED) ++set(TINYEXR_LIBRARIES "$;$>") + include(3rdparty/iqa.cmake) +-include(3rdparty/miniz.cmake) ++find_package(miniz CONFIG REQUIRED) ++set(MINIZ_LIBRARIES "$;$>") ++ ++find_package(Stb REQUIRED) ++ + include(bimg.cmake) + include(bimg_decode.cmake) + include(bimg_encode.cmake) +diff --git a/cmake/bimg/bimg_decode.cmake b/cmake/bimg/bimg_decode.cmake +index a511e8f..da98152 100644 +--- a/cmake/bimg/bimg_decode.cmake ++++ b/cmake/bimg/bimg_decode.cmake +@@ -34,6 +34,7 @@ target_include_directories( + PRIVATE ${LOADPNG_INCLUDE_DIR} # + ${MINIZ_INCLUDE_DIR} # + ${TINYEXR_INCLUDE_DIR} # ++ ${Stb_INCLUDE_DIR} + ) + + target_link_libraries( +diff --git a/cmake/bimg/bimg_encode.cmake b/cmake/bimg/bimg_encode.cmake +index 82d9fe0..a0ba5df 100644 +--- a/cmake/bimg/bimg_encode.cmake ++++ b/cmake/bimg/bimg_encode.cmake +@@ -32,6 +32,7 @@ target_include_directories( + ${TINYEXR_INCLUDE_DIR} # + ${IQA_INCLUDE_DIR} # + ${MINIZ_INCLUDE_DIR} # ++ ${Stb_INCLUDE_DIR} # + ) + + file( +diff --git a/cmake/bx/bx.cmake b/cmake/bx/bx.cmake +index d1a73c6..826c52b 100644 +--- a/cmake/bx/bx.cmake ++++ b/cmake/bx/bx.cmake +@@ -75,13 +75,14 @@ elseif(UNIX) + endif() + + # Add include directory of bx ++find_path(MGNLIBS_INCLUDE_DIR "mgnlibs/ini.h") + target_include_directories( + bx + PUBLIC $ # +- $ # + $ # + $ # + $ # ++ PRIVATE "${MGNLIBS_INCLUDE_DIR}" + ) + + # All configurations diff --git a/portfiles-switch/bgfx/portfile.cmake b/portfiles-switch/bgfx/portfile.cmake new file mode 100644 index 000000000..afb9b0212 --- /dev/null +++ b/portfiles-switch/bgfx/portfile.cmake @@ -0,0 +1,81 @@ +if(VCPKG_TARGET_IS_WINDOWS) + vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +endif() + +vcpkg_download_distfile( + ARCHIVE_FILE + URLS https://github.com/bkaradzic/bgfx.cmake/releases/download/v${VERSION}/bgfx.cmake.v${VERSION}.tar.gz + FILENAME bgfx.cmake.v${VERSION}.tar.gz + SHA512 520c542b65e76e92eae818e32eeb62bb2347ac89a1e10fc07cd5059a3b8a9a543cadca87d451a3bc157c415f6183b1f0e5031248e38fae704b8efd54679d482b +) + +vcpkg_extract_source_archive( + SOURCE_PATH + ARCHIVE "${ARCHIVE_FILE}" + PATCHES + fix-dependencies.patch + switch.patch +) +file(REMOVE_RECURSE + "${SOURCE_PATH}/bgfx/3rdparty/dear-imgui" + "${SOURCE_PATH}/bgfx/3rdparty/glslang" + "${SOURCE_PATH}/bgfx/3rdparty/khronos/EGL" + "${SOURCE_PATH}/bgfx/3rdparty/khronos/GLES3" + "${SOURCE_PATH}/bgfx/3rdparty/khronos/GLES2" + "${SOURCE_PATH}/bgfx/3rdparty/meshoptimizer" + "${SOURCE_PATH}/bgfx/3rdparty/spirv-cross" + "${SOURCE_PATH}/bgfx/3rdparty/spirv-headers" + "${SOURCE_PATH}/bgfx/3rdparty/spirv-opt" + "${SOURCE_PATH}/bgfx/3rdparty/stb" + "${SOURCE_PATH}/bimg/3rdparty/libsquish" + "${SOURCE_PATH}/bimg/3rdparty/lodepng" + "${SOURCE_PATH}/bimg/3rdparty/stb" + "${SOURCE_PATH}/bimg/3rdparty/tinyexr" +) + +vcpkg_check_features( + OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + tools BGFX_BUILD_TOOLS + multithreaded BGFX_CONFIG_MULTITHREADED +) + +if(VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) + set(BGFX_LIBRARY_TYPE "SHARED") +else () + set(BGFX_LIBRARY_TYPE "STATIC") +endif () + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DBGFX_LIBRARY_TYPE=${BGFX_LIBRARY_TYPE} + -DBGFX_AMALGAMATED=ON + -DBGFX_BUILD_EXAMPLES=OFF + -DBGFX_OPENGLES_VERSION=30 + "-DBGFX_ADDITIONAL_TOOL_PATHS=${CURRENT_INSTALLED_DIR}/../${HOST_TRIPLET}/tools/bgfx" + ${FEATURE_OPTIONS} + OPTIONS_DEBUG + -DBGFX_BUILD_TOOLS=OFF +) + +vcpkg_cmake_install() +vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/${PORT}") +vcpkg_copy_pdbs() + +if ("tools" IN_LIST FEATURES) + vcpkg_copy_tools(TOOL_NAMES bin2c shaderc geometryc texturec AUTO_CLEAN) +endif () + +vcpkg_install_copyright( + FILE_LIST "${CURRENT_PACKAGES_DIR}/share/licences/${PORT}/LICENSE" + COMMENT [[ +bgfx includes third-party components which are subject to specific license +terms. Check the sources for details. +]]) + +file(REMOVE_RECURSE + "${CURRENT_PACKAGES_DIR}/share/licences" + "${CURRENT_PACKAGES_DIR}/debug/include" + "${CURRENT_PACKAGES_DIR}/debug/share" +) \ No newline at end of file diff --git a/portfiles-switch/bgfx/switch.patch b/portfiles-switch/bgfx/switch.patch new file mode 100644 index 000000000..9775a1e9a --- /dev/null +++ b/portfiles-switch/bgfx/switch.patch @@ -0,0 +1,224 @@ +--- b/cmake/bgfx/bgfx.cmake ++++ b/cmake/bgfx/bgfx.cmake +@@ -176,18 +176,25 @@ + ) + endif() + ++if (ANDROID OR NX OR EMSCRIPTEN) ++ find_package(OpenGL REQUIRED COMPONENTS GLES2 GLES3 EGL) ++ target_link_libraries(bgfx PUBLIC OpenGL::GLES2 OpenGL::GLES3 OpenGL::EGL) ++else() ++ find_package(OpenGL REQUIRED) ++ target_link_libraries(bgfx PUBLIC OpenGL::GL) ++endif() ++ + if(UNIX + AND NOT APPLE + AND NOT EMSCRIPTEN + AND NOT ANDROID + ) + find_package(X11 REQUIRED) +- find_package(OpenGL REQUIRED) + #The following commented libraries are linked by bx + #find_package(Threads REQUIRED) + #find_library(LIBRT_LIBRARIES rt) + #find_library(LIBDL_LIBRARIES dl) +- target_link_libraries(bgfx PUBLIC ${X11_LIBRARIES} ${OPENGL_LIBRARIES}) ++ target_link_libraries(bgfx PUBLIC ${X11_LIBRARIES}) + endif() + + # Exclude mm files if not on OS X +--- a/bgfx/src/config.h ++++ b/bgfx/src/config.h +@@ -67,10 +67,9 @@ + ? 1 : 0) + # endif // BGFX_CONFIG_RENDERER_METAL + ++ + # ifndef BGFX_CONFIG_RENDERER_NVN +-# define BGFX_CONFIG_RENDERER_NVN (0 \ +- || BX_PLATFORM_NX \ +- ? 1 : 0) ++# define BGFX_CONFIG_RENDERER_NVN (0) + # endif // BGFX_CONFIG_RENDERER_NVN + + # ifndef BGFX_CONFIG_RENDERER_OPENGL_MIN_VERSION +@@ -104,7 +103,6 @@ + || BX_PLATFORM_ANDROID \ + || BX_PLATFORM_LINUX \ + || BX_PLATFORM_WINDOWS \ +- || BX_PLATFORM_NX \ + || BX_PLATFORM_OSX \ + ? 1 : 0) + # endif // BGFX_CONFIG_RENDERER_VULKAN +--- a/cmake/Config.cmake.in ++++ b/cmake/Config.cmake.in +@@ -17,6 +17,13 @@ + find_dependency(glslang CONFIG REQUIRED) + endif() + ++if (ANDROID OR NX OR EMSCRIPTEN) ++ find_dependency(OpenGL COMPONENTS GLES2 GLES3 EGL) ++else() ++ find_dependency(OpenGL) ++endif() ++ ++ + if(@BGFX_CMAKE_USER_SCRIPT_PRESENT@) + include("${CMAKE_CURRENT_LIST_DIR}/@BGFX_CMAKE_USER_SCRIPT_INSTALL_NAME@") + endif() +--- a/cmake/bgfxToolUtils.cmake ++++ b/cmake/bgfxToolUtils.cmake +@@ -382,10 +382,10 @@ + function(_bgfx_shaderc_parse ARG_OUT) + cmake_parse_arguments( + ARG +- "DEPENDS;ANDROID;ASM_JS;IOS;LINUX;OSX;WINDOWS;ORBIS;PREPROCESS;RAW;FRAGMENT;VERTEX;COMPUTE;VERBOSE;DEBUG;DISASM;WERROR" +- "FILE;OUTPUT;VARYINGDEF;BIN2C;PROFILE;O" +- "INCLUDES;DEFINES" +- ${ARGN} ++ "DEPENDS;ANDROID;ASM_JS;IOS;LINUX;OSX;WINDOWS;ORBIS;NX;PREPROCESS;RAW;FRAGMENT;VERTEX;COMPUTE;VERBOSE;DEBUG;DISASM;WERROR" ++ "FILE;OUTPUT;VARYINGDEF;BIN2C;PROFILE;O" ++ "INCLUDES;DEFINES" ++ ${ARGN} + ) + set(CLI "") + +@@ -423,7 +423,7 @@ + + # --platform + set(PLATFORM "") +- set(PLATFORMS "ANDROID;ASM_JS;IOS;LINUX;OSX;WINDOWS;ORBIS") ++ set(PLATFORMS "ANDROID;ASM_JS;IOS;LINUX;OSX;WINDOWS;ORBIS;NX") + foreach(P ${PLATFORMS}) + if(ARG_${P}) + if(PLATFORM) +@@ -600,6 +600,9 @@ + elseif(ORBIS) # ORBIS should be defined by a PS4 CMake toolchain + set(PLATFORM ORBIS) + list(APPEND PROFILES pssl) ++ elseif(NX) ++ set(PLATFORM NX) ++ list(APPEND PROFILES 320_es) + else() + # pssl for Agc and Gnm renderers + # nvn for Nvn renderer +--- a/bx/include/bx/platform.h ++++ b/bx/include/bx/platform.h +@@ -150,6 +150,15 @@ + #endif // BX_CPU_PPC + + // http://sourceforge.net/apps/mediawiki/predef/index.php?title=Operating_Systems ++#if defined(__has_builtin) ++# if __has_builtin(__is_target_os) ++# if __is_target_os(xros) ++# undef BX_PLATFORM_VISIONOS ++# define BX_PLATFORM_VISIONOS 1 ++# endif ++# endif ++#endif ++ + #if defined(_DURANGO) || defined(_XBOX_ONE) + # undef BX_PLATFORM_XBOXONE + # define BX_PLATFORM_XBOXONE 1 +@@ -196,9 +205,7 @@ + || defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) + # undef BX_PLATFORM_IOS + # define BX_PLATFORM_IOS 1 +-#elif defined(__has_builtin) && __has_builtin(__is_target_os) && __is_target_os(xros) +-# undef BX_PLATFORM_VISIONOS +-# define BX_PLATFORM_VISIONOS 1 ++#elif BX_PLATFORM_VISIONOS + #elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) + # undef BX_PLATFORM_OSX + # define BX_PLATFORM_OSX __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +--- a/bx/src/os.cpp ++++ b/bx/src/os.cpp +@@ -29,9 +29,9 @@ + # endif // BX_PLATFORM_* + + # include // nanosleep +-# if !BX_PLATFORM_PS4 ++# if !(BX_PLATFORM_PS4 || BX_PLATFORM_NX) + # include // dlopen, dlclose, dlsym +-# endif // !BX_PLATFORM_PS4 ++# endif // !BX_PLATFORM_* + + # if BX_PLATFORM_ANDROID + # include // mallinfo +--- a/bimg/3rdparty/nvtt/nvcore/nvcore.h ++++ b/bimg/3rdparty/nvtt/nvcore/nvcore.h +@@ -57,6 +57,8 @@ + # define NV_OS_WIN32 1 + #elif defined POSH_OS_XBOX + # define NV_OS_XBOX 1 ++#elif defined POSH_OS_NX ++# define NV_OS_NX 1 + #else + # error "Unsupported OS" + #endif +@@ -111,7 +113,7 @@ + + // Threading: + // some platforms don't implement __thread or similar for thread-local-storage +-#if NV_OS_UNIX || NV_OS_ORBIS || NV_OS_IOS //ACStodoIOS darwin instead of ios? ++#if NV_OS_UNIX || NV_OS_ORBIS || NV_OS_IOS || NV_OS_NX //ACStodoIOS darwin instead of ios? + # define NV_OS_USE_PTHREAD 1 + # if NV_OS_DARWIN || NV_OS_IOS + # define NV_OS_HAS_TLS_QUALIFIER 0 +@@ -181,6 +183,10 @@ + # define NV_CPU_EMSCRIPTEN 0 + #endif // NV_CPU_EMSCRIPTEN + ++#ifndef NV_OS_NX ++# define NV_OS_NX 0 ++#endif // NV_OS_NX ++ + // Compiler: + + #if defined POSH_COMPILER_CLANG +@@ -365,7 +371,7 @@ + # error "MSVC: Platform not supported" + # endif + #elif NV_CC_GNUC +-# if NV_OS_LINUX ++# if NV_OS_LINUX || NV_OS_NX + # include "defsgnuclinux.h" + # elif NV_OS_DARWIN || NV_OS_FREEBSD || NV_OS_OPENBSD + # include "defsgnucdarwin.h" +--- a/bimg/3rdparty/nvtt/nvcore/posh.h ++++ b/bimg/3rdparty/nvtt/nvcore/posh.h +@@ -435,6 +435,11 @@ + # define POSH_OS_STRING "MacOS" + #endif + ++#if defined __NX__ || defined __SWITCH__ ++# define POSH_OS_NX 1 ++# define POSH_OS_STRING "Switch" ++#endif ++ + /* + ** ----------------------------------------------------------------------------- + ** Determine target CPU +--- a/bimg/3rdparty/astc-encoder/source/astcenc_internal.h ++++ b/bimg/3rdparty/astc-encoder/source/astcenc_internal.h +@@ -30,6 +30,7 @@ + #endif + #include + #include ++#include + + #include "astcenc.h" + #include "astcenc_mathlib.h" +@@ -2197,8 +2197,10 @@ + + #if defined(_WIN32) + ptr = _aligned_malloc(size, real_align); ++#elif defined(HAVE_POSIX_MEMALIGN) ++ error = posix_memalign(&ptr, real_align, size); + #else +- error = posix_memalign(&ptr, real_align, size); ++ ptr = memalign(real_align, size); + #endif + + if (error || (!ptr)) diff --git a/portfiles-switch/bgfx/vcpkg.json b/portfiles-switch/bgfx/vcpkg.json new file mode 100644 index 000000000..1e01bb984 --- /dev/null +++ b/portfiles-switch/bgfx/vcpkg.json @@ -0,0 +1,55 @@ +{ + "name": "bgfx", + "version": "1.129.8940-496", + "port-version": 2, + "maintainers": "Sandy Carter ", + "description": "Cross-platform, graphics API agnostic, Bring Your Own Engine/Framework style rendering library.", + "homepage": "https://bkaradzic.github.io/bgfx/overview.html", + "documentation": "https://bkaradzic.github.io/bgfx", + "license": "BSD-2-Clause AND CC0-1.0", + "supports": "!bsd", + "dependencies": [ + "libsquish", + "lodepng", + "mgnlibs", + "miniz", + "stb", + "tinyexr", + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ], + "default-features": [ + { + "name": "multithreaded", + "platform": "!emscripten" + } + ], + "features": { + "multithreaded": { + "description": "Encode and render on different threads", + "supports": "!emscripten" + }, + "tools": { + "$comment": "Use '\"host\": true' in dependencies of vcpkg.json in manifest mode.", + "description": "Shader, Texture and Geometry compilers for bgfx.", + "dependencies": [ + "cgltf", + { + "name": "glslang", + "features": [ + "opt" + ] + }, + "meshoptimizer", + "spirv-cross", + "spirv-tools" + ] + } + } +} \ No newline at end of file diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index df81e40d8..c06fea76d 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -12,6 +12,11 @@ #include #endif +#ifdef __SWITCH__ +extern "C" { +#include +} +#endif namespace Impacto::Bgfx { constexpr bgfx::ViewId RENDER_VIEW = 0; // Uses render dimensions @@ -91,6 +96,8 @@ Renderer::Renderer() { initStruct.platformData.nwh = SDL_GetPointerProperty(SDL_GetWindowProperties(Window->SDLWindow), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr); +#elif defined(SDL_PLATFORM_SWITCH) + initStruct.platformData.nwh = nwindowGetDefault(); #else static_assert(false && "We have not implemented BGFX for this platform"); #endif diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h index 3e8e37b2a..ef2f21097 100644 --- a/src/renderer/bgfx/uniform.h +++ b/src/renderer/bgfx/uniform.h @@ -124,7 +124,8 @@ class UniformsState { bgfx::UniformInfo info; bgfx::getUniformInfo({handle}, info); - const auto uniformIt = std::ranges::find(uniformNames, info.name); + const auto uniformIt = + std::ranges::find(uniformNames, std::string_view{info.name}); assert(uniformIt != uniformNames.end() && "Uniforms struct needs to share the same uniform names as " "the shader source code"); diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 9c33ce682..a8379ab28 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -40,10 +40,8 @@ constexpr inline RendererType DefaultRendererType = RendererType::Direct3D12; #elif defined(SDL_PLATFORM_APPLE) RendererType::Metal; -#elif defined(SDL_PLATFORM_ANDROID) +#elif defined(SDL_PLATFORM_ANDROID) || defined(__SWITCH__) RendererType::OpenGLES; -#elif defined(__SWITCH__) - RendererType::Vulkan; #else RendererType{}; static_assert(false && "No default renderer supplied for target renderer"); From ecd68f9b2d99e90e8e74060820611c5d097fe1ca Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 15 Sep 2026 16:44:17 +0200 Subject: [PATCH 26/60] Crudely implement part of DrawPrimitives --- src/renderer/bgfx/renderer.cpp | 44 ++++++++++++++++++++++++++++++---- src/renderer/bgfx/renderer.h | 2 +- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index c06fea76d..2f0b41432 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -401,17 +401,21 @@ void Renderer::Flush() { bgfx::submit(RENDER_VIEW, CurrentState->ShaderProgram.get()); } -static bool ShouldFlip(const Sprite& sprite) { +static bool ShouldFlip(const SpriteSheet& sheet) { [[maybe_unused]] const RendererType rendererType = Impacto::Renderer->GetType(); - return sprite.Sheet.IsScreenCap && (false + return sheet.IsScreenCap && (false #ifdef IMPACTO_RENDERER_OPENGL - || rendererType == RendererType::OpenGL + || rendererType == RendererType::OpenGL #endif #ifdef IMPACTO_RENDERER_OPENGLES - || rendererType == RendererType::OpenGLES + || rendererType == RendererType::OpenGLES #endif - ); + ); +} + +static bool ShouldFlip(const Sprite& sprite) { + return ShouldFlip(sprite.Sheet); } void Renderer::InsertVertices( @@ -537,4 +541,34 @@ void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, InsertVertices(indices, vertices, ShouldFlip(sprite)); } +void Renderer::DrawPrimitives( + const SpriteSheet& sheet, const SpriteSheet* const mask, + const ShaderProgramType shaderType, + const std::span vertices, + const std::span indices, + const glm::mat4 spriteTransformation, const glm::mat4 maskTransformation, + const bool inverted, const TopologyMode topology, + const bool textureWrapRepeat) { + ShaderProgramInterface* const shader = [&]() -> ShaderProgramInterface* { + switch (shaderType) { + case ShaderProgramType::Sprite: + SpriteShader->SubmitUniforms({}, + {.s_texture = Textures[sheet.Texture]}); + return &*SpriteShader; + default: + break; + } + return nullptr; + }(); + + if (shader == nullptr) return; + + SetState({ + .ShaderProgram = *shader, + .Transformation = spriteTransformation, + }); + + InsertVertices(indices, vertices, ShouldFlip(sheet)); +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index e4f3bf256..cf558bd6f 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -82,7 +82,7 @@ class Renderer final : public BaseRenderer { std::span indices, glm::mat4 spriteTransformation, glm::mat4 maskTransformation, bool inverted, - TopologyMode topology, bool textureWrapRepeat) override {} + TopologyMode topology, bool textureWrapRepeat) override; void DrawCCMessageBox(Sprite const& sprite, Sprite const& mask, RectF const& dest, glm::vec4 tint, int alpha, From 7500d106d9f943bf885daa50c082834f4ec42285 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 15 Sep 2026 16:52:16 +0200 Subject: [PATCH 27/60] Independently set resolution from window size --- src/overlay.cpp | 121 ++++++++++++++++++++---------- src/renderer/bgfx/framebuffer.cpp | 3 +- src/renderer/bgfx/framebuffer.h | 5 ++ src/renderer/bgfx/renderer.cpp | 41 +++++++--- src/renderer/bgfx/renderer.h | 3 + src/renderer/opengl/renderer.h | 2 + src/renderer/renderer.h | 2 + src/renderer/window.cpp | 29 +++---- src/renderer/window.h | 4 +- src/userconfig.cpp | 6 +- src/userconfig.h | 7 +- 11 files changed, 154 insertions(+), 69 deletions(-) diff --git a/src/overlay.cpp b/src/overlay.cpp index f95865559..c565afa1e 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -352,54 +352,97 @@ static void ShowGamePicker(std::string& selectedGame) { ImGui::Spacing(); if (ImGui::CollapsingHeader("Display Settings", ImGuiTreeNodeFlags_DefaultOpen)) { - static std::string currentResolution; - - static std::optional lastResWidth; - static std::optional lastResHeight; - - if (currentResolution.empty() || - lastResWidth != gameSettings.ResolutionWidth || - lastResHeight != gameSettings.ResolutionHeight) { - if (gameSettings.ResolutionWidth && gameSettings.ResolutionHeight) { - currentResolution = fmt::format("{}x{}", *gameSettings.ResolutionWidth, - *gameSettings.ResolutionHeight); - } else { - currentResolution = "Native Game Res"; - } - wasUpdated = true; - lastResWidth = gameSettings.ResolutionWidth; - lastResHeight = gameSettings.ResolutionHeight; - } - SDL_DisplayMode maxRes{}; if (const SDL_DisplayMode* desktopMode = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay())) { maxRes = *desktopMode; } - ImGui::AlignTextToFramePadding(); - ImGui::Text("Game Resolution"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(comboWidth); - if (ImGui::BeginCombo("##ChooseResolution", currentResolution.c_str())) { - bool isNativeRes = - !gameSettings.ResolutionWidth || !gameSettings.ResolutionHeight; - if (ImGui::Selectable("Native Game Res", isNativeRes)) { - gameSettings.ResolutionWidth.reset(); - gameSettings.ResolutionHeight.reset(); + { + static std::string currentResolution; + + static std::optional lastResWidth; + static std::optional lastResHeight; + + if (currentResolution.empty() || + lastResWidth != gameSettings.ResolutionWidth || + lastResHeight != gameSettings.ResolutionHeight) { + if (gameSettings.ResolutionWidth && gameSettings.ResolutionHeight) { + currentResolution = + fmt::format("{}x{}", *gameSettings.ResolutionWidth, + *gameSettings.ResolutionHeight); + } else { + currentResolution = "Native Game Res"; + } + wasUpdated = true; + lastResWidth = gameSettings.ResolutionWidth; + lastResHeight = gameSettings.ResolutionHeight; } - if (isNativeRes) ImGui::SetItemDefaultFocus(); - for (auto&& [display, value] : resolutionOptions) { - if (value.x > maxRes.w || value.y > maxRes.h) continue; - bool isSelected = gameSettings.ResolutionWidth == value.x && - gameSettings.ResolutionHeight == value.y; - if (ImGui::Selectable(display, isSelected)) { - gameSettings.ResolutionWidth = value.x; - gameSettings.ResolutionHeight = value.y; + + ImGui::AlignTextToFramePadding(); + ImGui::Text("Game Resolution"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(comboWidth); + if (ImGui::BeginCombo("##ChooseResolution", currentResolution.c_str())) { + bool isNativeRes = + !gameSettings.ResolutionWidth || !gameSettings.ResolutionHeight; + if (ImGui::Selectable("Native Game Res", isNativeRes)) { + gameSettings.ResolutionWidth.reset(); + gameSettings.ResolutionHeight.reset(); } - if (isSelected) ImGui::SetItemDefaultFocus(); + if (isNativeRes) ImGui::SetItemDefaultFocus(); + for (auto&& [display, value] : resolutionOptions) { + if (value.x > maxRes.w || value.y > maxRes.h) continue; + bool isSelected = gameSettings.ResolutionWidth == value.x && + gameSettings.ResolutionHeight == value.y; + if (ImGui::Selectable(display, isSelected)) { + gameSettings.ResolutionWidth = value.x; + gameSettings.ResolutionHeight = value.y; + } + if (isSelected) ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + } + + { + static std::string currentWindowSize; + + static int lastWindowWidth; + static int lastWindowHeight; + + if (currentWindowSize.empty() || + lastWindowWidth != gameSettings.WindowWidth || + lastWindowHeight != gameSettings.WindowHeight) { + if (!gameSettings.WindowWidth || !gameSettings.WindowHeight) { + gameSettings.WindowWidth = UserConfig::CommonSettings.WindowWidth; + gameSettings.WindowHeight = UserConfig::CommonSettings.WindowHeight; + } + + currentWindowSize = fmt::format("{}x{}", *gameSettings.WindowWidth, + *gameSettings.WindowHeight); + + wasUpdated = true; + lastWindowWidth = *gameSettings.WindowWidth; + lastWindowHeight = *gameSettings.WindowHeight; + } + + ImGui::Text("Window Size"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(comboWidth); + if (ImGui::BeginCombo("##ChooseWindowSize", currentWindowSize.c_str())) { + for (auto&& [display, value] : resolutionOptions) { + if (value.x > maxRes.w || value.y > maxRes.h) continue; + bool isSelected = gameSettings.WindowWidth == value.x && + gameSettings.WindowHeight == value.y; + if (ImGui::Selectable(display, isSelected)) { + gameSettings.WindowWidth = value.x; + gameSettings.WindowHeight = value.y; + } + if (isSelected) ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); } - ImGui::EndCombo(); } ImGui::SameLine(); diff --git a/src/renderer/bgfx/framebuffer.cpp b/src/renderer/bgfx/framebuffer.cpp index 223abb0f5..70c905db7 100644 --- a/src/renderer/bgfx/framebuffer.cpp +++ b/src/renderer/bgfx/framebuffer.cpp @@ -23,7 +23,8 @@ FrameBuffer::~FrameBuffer() { Reset(true); } FrameBuffer::FrameBuffer(const uint16_t width, const uint16_t height) : ColorAttachment(bgfx::createTexture2D(width, height, false, 1, bgfx::TextureFormat::RGBA8, - BGFX_TEXTURE_RT)) { + BGFX_TEXTURE_RT)), + Size(width, height) { assert(bgfx::isValid(ColorAttachment)); FrameBufferHandle = bgfx::createFrameBuffer(1, &ColorAttachment, true); diff --git a/src/renderer/bgfx/framebuffer.h b/src/renderer/bgfx/framebuffer.h index 1a6aa3bae..abad9efae 100644 --- a/src/renderer/bgfx/framebuffer.h +++ b/src/renderer/bgfx/framebuffer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -37,10 +38,14 @@ class FrameBuffer { return bgfx::getTexture(FrameBufferHandle, 0); } + [[nodiscard]] glm::ivec2 GetSize() const { return Size; } + private: bgfx::FrameBufferHandle FrameBufferHandle = {bgfx::kInvalidHandle}; bgfx::TextureHandle ColorAttachment = {bgfx::kInvalidHandle}; + glm::ivec2 Size; + void Reset(bool cleanUpResources); }; diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 2f0b41432..2e20945f5 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -62,8 +62,8 @@ Renderer::Renderer() { "Initializing BGFX with {:s} backend", magic_enum::enum_name(initStruct.type)); - initStruct.resolution.width = UserConfig::CommonSettings.ResolutionWidth; - initStruct.resolution.height = UserConfig::CommonSettings.ResolutionHeight; + initStruct.resolution.width = UserConfig::CommonSettings.WindowWidth; + initStruct.resolution.height = UserConfig::CommonSettings.WindowHeight; initStruct.resolution.reset = BGFX_RESET_VSYNC; #if defined(SDL_PLATFORM_WIN32) initStruct.platformData.nwh = @@ -193,9 +193,9 @@ Renderer::Renderer() { void Renderer::Init() { [[maybe_unused]] const RendererType type = GetType(); - DrawFrameBuffer = - FrameBuffer(static_cast(Profile::Game::DesignWidth), - static_cast(Profile::Game::DesignHeight)); + UpdateResolution(); + DrawFrameBuffer = FrameBuffer(static_cast(Resolution.x), + static_cast(Resolution.y)); const glm::mat4 projectionMatrix = glm::ortho(0.0f, Profile::Game::DesignWidth, Profile::Game::DesignHeight, @@ -204,10 +204,6 @@ void Renderer::Init() { bgfx::setViewTransform(RENDER_VIEW, glm::value_ptr(identityMatrix), glm::value_ptr(projectionMatrix)); - bgfx::setViewRect(RENDER_VIEW, 0, 0, - static_cast(Profile::Game::DesignWidth), - static_cast(Profile::Game::DesignHeight)); - constexpr static std::array backBufferIndices = { 0, 1, 3, 1, 2, 3, }; @@ -244,6 +240,26 @@ void Renderer::Init() { VertexBufferSpritesLayout); } +void Renderer::UpdateResolution() { + const auto& gameConfig = UserConfig::ActiveGameSettings(); + + if (gameConfig.ResolutionWidth.has_value() != + gameConfig.ResolutionHeight.has_value()) { + ImpLog(LogLevel::Warning, LogChannel::Render, + "Only one of Resolution Height or Resolution Width is configured, " + "defaulting to native game resolution."); + } + + // Queue up new resolution for seamless switching between the end of the + // current frame and the start of the next + Resolution = + gameConfig.ResolutionWidth.has_value() && + gameConfig.ResolutionHeight.has_value() + ? glm::ivec2{*gameConfig.ResolutionWidth, + *gameConfig.ResolutionHeight} + : glm::ivec2{Profile::Game::DesignWidth, Profile::Game::DesignHeight}; +} + RendererType Renderer::GetType() const { switch (bgfx::getRendererType()) { using enum bgfx::RendererType::Enum; @@ -293,7 +309,14 @@ void Renderer::BeginFrame() { } void Renderer::BeginFrame2D() { + if (DrawFrameBuffer.GetSize() != Resolution) { + DrawFrameBuffer = FrameBuffer(static_cast(Resolution.x), + static_cast(Resolution.y)); + } + bgfx::setViewFrameBuffer(RENDER_VIEW, DrawFrameBuffer); + bgfx::setViewRect(RENDER_VIEW, 0, 0, static_cast(Resolution.x), + static_cast(Resolution.y)); bgfx::touch(RENDER_VIEW); } diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index cf558bd6f..2ad8d9d3c 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -19,6 +19,8 @@ class Renderer final : public BaseRenderer { void Init() override; void Shutdown() override; + void UpdateResolution() override; + RendererType GetType() const override; #ifndef IMPACTO_DISABLE_IMGUI @@ -155,6 +157,7 @@ class Renderer final : public BaseRenderer { std::optional CurrentState = std::nullopt; FrameBuffer DrawFrameBuffer; + glm::ivec2 Resolution; bgfx::DynamicIndexBufferHandle IndexBuffer = {bgfx::kInvalidHandle}; bgfx::DynamicVertexBufferHandle VertexBuffer = {bgfx::kInvalidHandle}; diff --git a/src/renderer/opengl/renderer.h b/src/renderer/opengl/renderer.h index 5a26b943d..4b8a86e4b 100644 --- a/src/renderer/opengl/renderer.h +++ b/src/renderer/opengl/renderer.h @@ -23,6 +23,8 @@ class Renderer : public BaseRenderer { void Init() override; void Shutdown() override; + void UpdateResolution() override {} + RendererType GetType() const override { return RendererType::OpenGLLegacy; } #ifndef IMPACTO_DISABLE_IMGUI diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index a8379ab28..b10fe92b7 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -105,6 +105,8 @@ class BaseRenderer { virtual void Init() = 0; virtual void Shutdown() = 0; + virtual void UpdateResolution() = 0; + virtual RendererType GetType() const = 0; #ifndef IMPACTO_DISABLE_IMGUI diff --git a/src/renderer/window.cpp b/src/renderer/window.cpp index 8d4be3782..07602ebfa 100644 --- a/src/renderer/window.cpp +++ b/src/renderer/window.cpp @@ -354,8 +354,8 @@ RectF BaseWindow::GetScaledViewport() { bool BaseWindow::CreateSDLWindow(SDL_WindowFlags flags) { auto const& config = UserConfig::CommonSettings; - WindowWidth = config.ResolutionWidth; - WindowHeight = config.ResolutionHeight; + WindowWidth = config.WindowWidth; + WindowHeight = config.WindowHeight; #if IMPACTO_USE_SDL_HIGHDPI flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY; @@ -381,27 +381,26 @@ bool BaseWindow::CreateSDLWindow(SDL_WindowFlags flags) { void BaseWindow::ApplyWindowSettings() { auto const& config = UserConfig::CommonSettings; - WindowWidth = config.ResolutionWidth; - WindowHeight = config.ResolutionHeight; + WindowWidth = config.WindowWidth; + WindowHeight = config.WindowHeight; DisplayMode dispMode = GetDefaultDispMode(); if (!UserConfig::GetActiveGame().empty()) { auto const& gameConfig = UserConfig::ActiveGameSettings(); - if (gameConfig.ResolutionHeight.has_value() ^ - gameConfig.ResolutionHeight.has_value()) { + if (gameConfig.WindowWidth.has_value() ^ + gameConfig.WindowWidth.has_value()) { ImpLog(LogLevel::Warning, LogChannel::Render, - "Only one of Resolution Height or Resolution Width is configured, " - "defaulting to game resolution."); + "Only one of Window Height or Window Width is configured, " + "defaulting to application settings."); } - if (gameConfig.ResolutionWidth && gameConfig.ResolutionHeight) { - WindowWidth = *gameConfig.ResolutionWidth; - WindowHeight = *gameConfig.ResolutionHeight; - } else if (Profile::Game::HasInit) { - WindowWidth = static_cast(Profile::Game::DesignWidth); - WindowHeight = static_cast(Profile::Game::DesignHeight); + + if (gameConfig.WindowWidth && gameConfig.WindowHeight) { + WindowWidth = *gameConfig.WindowWidth; + WindowHeight = *gameConfig.WindowHeight; } + dispMode = gameConfig.Display; } @@ -432,6 +431,8 @@ void BaseWindow::ApplyWindowSettings() { DpiScale = SDL_GetWindowDisplayScale(SDLWindow); RecreateFBOs = true; Update(); + + Renderer->UpdateResolution(); } bool HandleWindowEvents(SDL_Event const* evt) { diff --git a/src/renderer/window.h b/src/renderer/window.h index 26dbf6c3f..c8278ccb2 100644 --- a/src/renderer/window.h +++ b/src/renderer/window.h @@ -53,8 +53,8 @@ class BaseWindow { SDL_Window* SDLWindow; - // Raw dimensions without aspect ratio correction. Only use for - // setting/determining resolution and drawing to window framebuffer! + // Raw dimensions without aspect ratio correction. Only use for drawing to + // window framebuffer! int WindowWidth = 0; int WindowHeight = 0; diff --git a/src/userconfig.cpp b/src/userconfig.cpp index 515eac49a..301ce4c3a 100644 --- a/src/userconfig.cpp +++ b/src/userconfig.cpp @@ -98,6 +98,8 @@ TOML11_DEFINE_CONVERSION_NON_INTRUSIVE( Impacto::UserConfig::GameConfig, ResolutionWidth, ResolutionHeight, + WindowWidth, + WindowHeight, PatchProfile, UsePatch, Display @@ -105,8 +107,8 @@ TOML11_DEFINE_CONVERSION_NON_INTRUSIVE( TOML11_DEFINE_CONVERSION_NON_INTRUSIVE( Impacto::UserConfig::Config, - ResolutionWidth, - ResolutionHeight, + WindowWidth, + WindowHeight, LogFile, LogLvl, LogChannels, diff --git a/src/userconfig.h b/src/userconfig.h index 0646f372f..4cf88e08c 100644 --- a/src/userconfig.h +++ b/src/userconfig.h @@ -35,13 +35,16 @@ namespace UserConfig { struct GameConfig { std::optional ResolutionWidth; std::optional ResolutionHeight; + std::optional WindowWidth; + std::optional WindowHeight; + std::string PatchProfile; bool UsePatch; DisplayMode Display = GetDefaultDispMode(); }; struct Config { - int ResolutionWidth = 1280; - int ResolutionHeight = 720; + int WindowWidth = 1280; + int WindowHeight = 720; std::string LogFile = GetDefaultLogFile(); LogLevel LogLvl = LogLevel::Warning; From c75f5ebbfc48936f9b87ca916400061cd9788cef Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Tue, 15 Sep 2026 17:54:24 +0200 Subject: [PATCH 28/60] Call bgfx::setState for each submitted batch of vertices --- src/renderer/bgfx/renderer.cpp | 53 ++++++++++++++++------------------ 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 2e20945f5..31a74b721 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -117,12 +117,9 @@ Renderer::Renderer() { glm::value_ptr(identityMatrix)); constexpr uint32_t black = 0x000000ff; + bgfx::setViewClear(RENDER_VIEW, BGFX_CLEAR_COLOR | BGFX_CLEAR_STENCIL, black); bgfx::setViewClear(DISPLAY_VIEW, BGFX_CLEAR_COLOR, black); - constexpr uint32_t transparentWhite = 0xffffff00; - bgfx::setViewClear(RENDER_VIEW, BGFX_CLEAR_COLOR | BGFX_CLEAR_STENCIL, - transparentWhite); - IndexBuffer = bgfx::createDynamicIndexBuffer(static_cast(0), BGFX_BUFFER_ALLOW_RESIZE); if (!bgfx::isValid(IndexBuffer)) { @@ -350,6 +347,7 @@ void Renderer::EndFrame() { bgfx::setVertexBuffer(0, BackBufferVertexBuffer); SpriteShader->SubmitUniforms({}, {.s_texture = DrawFrameBuffer.GetTexture()}); + bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_DEPTH_TEST_ALWAYS); bgfx::submit(DISPLAY_VIEW, *SpriteShader); } @@ -421,6 +419,29 @@ void Renderer::Flush() { CurFrameIndexBufferOffset = Indices.size(); CurFrameVertexBufferOffset = Vertices.size(); + { + uint64_t stateFlags = BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A; + + switch (CurrentState->BlendMode) { + using enum RendererBlendMode; + case Normal: + stateFlags |= BGFX_STATE_BLEND_FUNC_SEPARATE( + BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA, + BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE); + break; + case Additive: + stateFlags |= BGFX_STATE_BLEND_FUNC_SEPARATE( + BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE, + BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE); + break; + case Premultiplied: + stateFlags |= BGFX_STATE_BLEND_NORMAL; + break; + } + + bgfx::setState(stateFlags); + } + bgfx::submit(RENDER_VIEW, CurrentState->ShaderProgram.get()); } @@ -470,10 +491,6 @@ void Renderer::InsertVertices( } void Renderer::SetState(const CommandBuffer& newState) { - uint64_t stateFlags = - BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A | BGFX_STATE_DEPTH_TEST_ALWAYS; - bool differentStateFlags = !CurrentState.has_value(); - if (!CurrentState.has_value() || CurrentState->Transformation != newState.Transformation) { Flush(); @@ -488,27 +505,7 @@ void Renderer::SetState(const CommandBuffer& newState) { if (!CurrentState.has_value() || CurrentState->BlendMode != newState.BlendMode) { Flush(); - differentStateFlags = true; } - switch (newState.BlendMode) { - using enum RendererBlendMode; - case Normal: - stateFlags |= BGFX_STATE_BLEND_FUNC_SEPARATE( - BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA, - BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE); - break; - case Additive: - stateFlags |= BGFX_STATE_BLEND_FUNC_SEPARATE( - BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_ONE, - BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE); - break; - case Premultiplied: - stateFlags |= BGFX_STATE_BLEND_NORMAL; - break; - } - - if (differentStateFlags) Flush(); - bgfx::setState(stateFlags); CurrentState = newState; } From 5f2e15eb134004a29f7a9c6581fbec96ca1628db Mon Sep 17 00:00:00 2001 From: Dextinfire <> Date: Wed, 16 Sep 2026 00:45:48 -0700 Subject: [PATCH 29/60] fix android builds --- .github/workflows/impacto.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/impacto.yml b/.github/workflows/impacto.yml index 63a171086..4375ad71d 100644 --- a/.github/workflows/impacto.yml +++ b/.github/workflows/impacto.yml @@ -121,7 +121,6 @@ jobs: export MINSDKVERSION=28 echo "MINSDKVERSION=$MINSDKVERSION" >> $GITHUB_ENV echo "ABI=$ABI" >> $GITHUB_ENV - echo "CC=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=aarch64-linux-android$MINSDKVERSION -fPIC" >> $GITHUB_ENV echo "VULKAN_SDK=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr" >> $GITHUB_ENV shell: bash From 56d64148f58c3c774f3d8ba418bc5b00c28718af Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Wed, 16 Sep 2026 23:52:17 +0200 Subject: [PATCH 30/60] Declare sampler stage in uniform struct --- src/renderer/bgfx/shaders/fs_sprite.h | 2 +- src/renderer/bgfx/uniform.h | 53 +++++++++++++++++++-------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/renderer/bgfx/shaders/fs_sprite.h b/src/renderer/bgfx/shaders/fs_sprite.h index 2d3ff03f4..621b726ac 100644 --- a/src/renderer/bgfx/shaders/fs_sprite.h +++ b/src/renderer/bgfx/shaders/fs_sprite.h @@ -6,7 +6,7 @@ namespace Impacto::Bgfx { template <> struct Uniforms { - bgfx::TextureHandle s_texture = {bgfx::kInvalidHandle}; + SamplerUniform<0> s_texture; glm::vec3 u_colorShift = glm::vec3(0.0f); }; diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h index ef2f21097..876ff7c47 100644 --- a/src/renderer/bgfx/uniform.h +++ b/src/renderer/bgfx/uniform.h @@ -6,14 +6,25 @@ #include #include "../renderer.h" - -inline bool operator!=(const bgfx::TextureHandle& lhs, - const bgfx::TextureHandle& rhs) { - return lhs.idx != rhs.idx; -} +#include "texture.h" namespace Impacto::Bgfx { +template +struct SamplerUniform { + SamplerUniform() = default; + SamplerUniform(bgfx::TextureHandle handle) : Handle(handle) {} + SamplerUniform(Texture& texture) : Handle(texture.GetTextureHandle()) {} + + bgfx::TextureHandle Handle = {bgfx::kInvalidHandle}; + + bool operator==(const SamplerUniform& other) const { + return Handle.idx == other.Handle.idx; + } + + constexpr uint8_t GetStage() { return stage; } +}; + template constexpr bgfx::UniformType::Enum GetUniformType(); @@ -26,15 +37,24 @@ constexpr bgfx::UniformType::Enum GetUniformType() { } template <> -constexpr bgfx::UniformType::Enum GetUniformType() { - return bgfx::UniformType::Sampler; +constexpr bgfx::UniformType::Enum GetUniformType() { + return bgfx::UniformType::Vec4; +} + +template <> +constexpr bgfx::UniformType::Enum GetUniformType() { + return bgfx::UniformType::Vec4; } template -void SetUniform(bgfx::UniformHandle handle, const T& value); + requires requires(T sampler) { + { SamplerUniform(sampler) } -> std::same_as; + } +constexpr bgfx::UniformType::Enum GetUniformType() { + return bgfx::UniformType::Sampler; +} -template <> -inline void SetUniform(bgfx::UniformHandle handle, const glm::vec4& value) { +inline void SetUniform(bgfx::UniformHandle handle, glm::vec4 value) { static_assert(GetUniformType>() == bgfx::UniformType::Vec4); @@ -52,18 +72,21 @@ inline void SetUniform(bgfx::UniformHandle handle, const T& value) { bgfx::setUniform(handle, glm::value_ptr(vec4), 1); } -template <> -inline void SetUniform(bgfx::UniformHandle handle, const float& value) { +inline void SetUniform(bgfx::UniformHandle handle, float value) { SetUniform(handle, glm::vec1(value)); } -template <> +inline void SetUniform(bgfx::UniformHandle handle, bool value) { + SetUniform(handle, value ? 1.0f : 0.0f); +} + +template inline void SetUniform(bgfx::UniformHandle handle, - const bgfx::TextureHandle& value) { + SamplerUniform value) { static_assert(GetUniformType>() == bgfx::UniformType::Sampler); - bgfx::setTexture(0, handle, value); + bgfx::setTexture(stage, handle, value.Handle); } enum class VertexShaderType { From af0204a5eb0e37952795899979c2ff0d37c284ec Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Wed, 16 Sep 2026 23:55:04 +0200 Subject: [PATCH 31/60] Allow for declaring textures into the renderer --- src/renderer/bgfx/renderer.cpp | 94 ++++++++++++++++++++++------------ src/renderer/bgfx/renderer.h | 13 +++++ 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 31a74b721..ca347c6a7 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -365,14 +365,31 @@ void Renderer::ImGuiBeginFrame() { uint32_t Renderer::SubmitTexture(const TexFmt format, const std::span buffer, const int width, const int height) { + const bgfx::TextureFormat::Enum bgfxFormat = [format]() { + switch (format) { + case TexFmt::TexFmt_U8: + return bgfx::TextureFormat::R8; + case TexFmt::TexFmt_RGB: + return bgfx::TextureFormat::RGB8; + case TexFmt::TexFmt_RGBA: + return bgfx::TextureFormat::RGBA8; + } + Panic(LogChannel::Render, "Unexpected texture format \"{:s}\"", + magic_enum::enum_name(format)); + }(); + + return DeclareTexture(std::make_unique(bgfxFormat, buffer, + static_cast(width), + static_cast(height))) + ->first; +} + +decltype(Renderer::Textures)::iterator Renderer::DeclareTexture( + std::unique_ptr&& texture) { static uint32_t curTextureId = 1; const uint32_t textureId = curTextureId++; - Textures.emplace(textureId, - Texture(format, buffer, static_cast(width), - static_cast(height))); - - return textureId; + return Textures.emplace(textureId, std::move(texture)).first; } void Renderer::FreeTexture(const uint32_t id) { @@ -528,37 +545,11 @@ void Renderer::DrawSprite(const Sprite& sprite, const CornersQuad& dest, SpriteShader->SubmitUniforms({}, { - .s_texture = Textures[sprite.Sheet.Texture], + .s_texture = *Textures[sprite.Sheet.Texture], .u_colorShift = colorShift, }); - const RectF normalizedBounds = sprite.NormalizedBounds(); - - constexpr static std::array indices = {0, 1, 3, 1, 2, 3}; - const std::array vertices = { - VertexBufferSprites{ - .Position = dest.TopLeft, - .UV = normalizedBounds.TopLeft(), - .Tint = tints[0], - }, - VertexBufferSprites{ - .Position = dest.BottomLeft, - .UV = normalizedBounds.BottomLeft(), - .Tint = tints[1], - }, - VertexBufferSprites{ - .Position = dest.BottomRight, - .UV = normalizedBounds.BottomRight(), - .Tint = tints[2], - }, - VertexBufferSprites{ - .Position = dest.TopRight, - .UV = normalizedBounds.TopRight(), - .Tint = tints[3], - }, - }; - - InsertVertices(indices, vertices, ShouldFlip(sprite)); + InsertQuad(dest, sprite.NormalizedBounds(), tints, ShouldFlip(sprite)); } void Renderer::DrawPrimitives( @@ -573,7 +564,7 @@ void Renderer::DrawPrimitives( switch (shaderType) { case ShaderProgramType::Sprite: SpriteShader->SubmitUniforms({}, - {.s_texture = Textures[sheet.Texture]}); + {.s_texture = *Textures[sheet.Texture]}); return &*SpriteShader; default: break; @@ -591,4 +582,39 @@ void Renderer::DrawPrimitives( InsertVertices(indices, vertices, ShouldFlip(sheet)); } +void Renderer::InsertQuad(const CornersQuad dest, const CornersQuad uvs, + const std::span tints, + const bool flipVertically, + const CornersQuad maskUvs) { + constexpr static std::array indices = {0, 1, 3, 1, 2, 3}; + const std::array vertices = { + VertexBufferSprites{ + .Position = dest.TopLeft, + .UV = uvs.TopLeft, + .Tint = tints[0], + .MaskUV = maskUvs.TopLeft, + }, + VertexBufferSprites{ + .Position = dest.BottomLeft, + .UV = uvs.BottomLeft, + .Tint = tints[1], + .MaskUV = maskUvs.BottomLeft, + }, + VertexBufferSprites{ + .Position = dest.BottomRight, + .UV = uvs.BottomRight, + .Tint = tints[2], + .MaskUV = maskUvs.BottomRight, + }, + VertexBufferSprites{ + .Position = dest.TopRight, + .UV = uvs.TopRight, + .Tint = tints[3], + .MaskUV = maskUvs.TopRight, + }, + }; + + InsertVertices(indices, vertices, flipVertically); +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index 2ad8d9d3c..d0e1dedb7 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -139,6 +139,15 @@ class Renderer final : public BaseRenderer { std::span vertices, bool flipVertically); + void InsertQuad(CornersQuad dest, CornersQuad uvs, + std::span tints, bool flipVertically, + CornersQuad maskUvs = RectF{}); + void InsertQuad(CornersQuad dest, CornersQuad uvs, glm::vec4 tint, + bool flipVertically, CornersQuad maskUvs = RectF{}) { + InsertQuad(dest, uvs, std::array{tint, tint, tint, tint}, + flipVertically, maskUvs); + } + // Only call bgfx::shutdown after all managed objects in this class have been // default-destructed struct BgfxHandleStruct { @@ -175,6 +184,10 @@ class Renderer final : public BaseRenderer { ShaderProgram> SpriteShader; + std::map> Textures; + decltype(Textures)::iterator DeclareTexture( + std::unique_ptr&& texture); + std::map Textures; }; From 41de4f1ccea2954d7c60429fbe012f92dfb2a9f0 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Wed, 16 Sep 2026 23:55:42 +0200 Subject: [PATCH 32/60] Add MutableTexture type --- src/renderer/bgfx/texture.cpp | 54 ++++++++++++++++++++++++----------- src/renderer/bgfx/texture.h | 19 +++++++++--- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/renderer/bgfx/texture.cpp b/src/renderer/bgfx/texture.cpp index 107bed12d..a55fe5ff9 100644 --- a/src/renderer/bgfx/texture.cpp +++ b/src/renderer/bgfx/texture.cpp @@ -9,35 +9,25 @@ Texture& Texture::operator=(Texture&& other) { Reset(true); Handle = other.Handle; + Width = other.Width; + Height = other.Height; other.Reset(false); return *this; } -Texture::Texture(const TexFmt format, const std::span data, - const size_t width, const size_t height) { - const bgfx::TextureFormat::Enum bgfxTextureFormat = - [format]() -> bgfx::TextureFormat::Enum { - switch (format) { - case TexFmt_RGB: - return bgfx::TextureFormat::RGB8; - case TexFmt_RGBA: - return bgfx::TextureFormat::RGBA8; - case TexFmt_U8: - return bgfx::TextureFormat::R8; - } - assert(false); - return bgfx::TextureFormat::RGBA8; - }(); - +Texture::Texture(const bgfx::TextureFormat::Enum format, + const std::span data, const size_t width, + const size_t height) + : Width(width), Height(height) { constexpr uint64_t textureFlags = BGFX_SAMPLER_MIN_ANISOTROPIC | // BGFX_SAMPLER_MAG_ANISOTROPIC | // BGFX_SAMPLER_UVW_CLAMP; Handle = bgfx::createTexture2D( static_cast(width), static_cast(height), false, 1, - bgfxTextureFormat, textureFlags, + format, textureFlags, bgfx::copy(data.data(), static_cast(data.size_bytes()))); if (!bgfx::isValid(Handle)) { @@ -54,4 +44,34 @@ void Texture::Reset(const bool cleanUpResources) { Handle.idx = bgfx::kInvalidHandle; } +MutableTexture::MutableTexture(const bgfx::TextureFormat::Enum format, + const size_t width, const size_t height) { + Width = width; + Height = height; + + constexpr uint64_t textureFlags = BGFX_SAMPLER_MIN_ANISOTROPIC | // + BGFX_SAMPLER_MAG_ANISOTROPIC | // + BGFX_SAMPLER_UVW_CLAMP; + + Handle = bgfx::createTexture2D(static_cast(width), + static_cast(height), false, 1, + format, textureFlags, nullptr); + + if (!bgfx::isValid(Handle)) { + ImpLog(LogLevel::Error, LogChannel::Render, "Failed to create texture."); + assert(false); + } +} + +void MutableTexture::Update(const std::span data, + const uint16_t stride) { + assert(bgfx::isValid(Handle)); + + bgfx::updateTexture2D( + Handle, 0, 0, 0, 0, static_cast(Width), + static_cast(Height), + bgfx::copy(data.data(), static_cast(data.size_bytes())), + stride); +} + } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/texture.h b/src/renderer/bgfx/texture.h index 0192e0d0e..327179d3c 100644 --- a/src/renderer/bgfx/texture.h +++ b/src/renderer/bgfx/texture.h @@ -14,7 +14,7 @@ class Texture { Texture() = default; Texture(Texture&) = delete; Texture(Texture&& other) { *this = std::move(other); } - ~Texture() { Reset(true); } + virtual ~Texture() { Reset(true); } Texture& operator=(Texture&) = delete; Texture& operator=(Texture&&); @@ -23,8 +23,8 @@ class Texture { return other.Handle.idx == Handle.idx; } - Texture(TexFmt format, std::span data, size_t width, - size_t height); + Texture(bgfx::TextureFormat::Enum format, std::span data, + size_t width, size_t height); operator bgfx::TextureHandle() { return GetTextureHandle(); } bgfx::TextureHandle GetTextureHandle() { @@ -32,10 +32,21 @@ class Texture { return Handle; } - private: + protected: bgfx::TextureHandle Handle = {bgfx::kInvalidHandle}; + size_t Width = 0; + size_t Height = 0; + void Reset(bool cleanUpResources); }; +class MutableTexture final : public Texture { + public: + MutableTexture() = default; + MutableTexture(bgfx::TextureFormat::Enum format, size_t width, size_t height); + + void Update(std::span data, uint16_t stride); +}; + } // namespace Impacto::Bgfx From a324f8775b402cba49fe2635ac22b1e36fb480e7 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Wed, 16 Sep 2026 23:56:36 +0200 Subject: [PATCH 33/60] Implement NV12 and YUV video rendering --- CMakeLists.txt | 10 ++++ src/renderer/bgfx/renderer.cpp | 49 ++++++++++++++++++ src/renderer/bgfx/renderer.h | 28 ++++++---- src/renderer/bgfx/shader.h | 2 + src/renderer/bgfx/shaders/fs_nv12frame.h | 14 +++++ src/renderer/bgfx/shaders/fs_yuvframe.h | 15 ++++++ src/renderer/bgfx/uniform.h | 12 +++-- src/renderer/bgfx/video/nv12frame.cpp | 56 ++++++++++++++++++++ src/renderer/bgfx/video/nv12frame.h | 21 ++++++++ src/renderer/bgfx/video/yuvframe.cpp | 65 ++++++++++++++++++++++++ src/renderer/bgfx/video/yuvframe.h | 21 ++++++++ src/renderer/nv12frame.h | 5 +- src/renderer/yuvframe.h | 7 +-- src/shaders/bgfx/fs_nv12frame.sc | 37 ++++++++++++++ src/shaders/bgfx/fs_yuvframe.sc | 39 ++++++++++++++ src/shaders/bgfx/vs_sprite.sc | 2 +- 16 files changed, 362 insertions(+), 21 deletions(-) create mode 100644 src/renderer/bgfx/shaders/fs_nv12frame.h create mode 100644 src/renderer/bgfx/shaders/fs_yuvframe.h create mode 100644 src/renderer/bgfx/video/nv12frame.cpp create mode 100644 src/renderer/bgfx/video/nv12frame.h create mode 100644 src/renderer/bgfx/video/yuvframe.cpp create mode 100644 src/renderer/bgfx/video/yuvframe.h create mode 100644 src/shaders/bgfx/fs_nv12frame.sc create mode 100644 src/shaders/bgfx/fs_yuvframe.sc diff --git a/CMakeLists.txt b/CMakeLists.txt index ca9a84fce..9802405cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1253,6 +1253,9 @@ if (IMPACTO_RENDERER_BGFX) src/renderer/bgfx/renderer.cpp src/renderer/bgfx/texture.cpp src/renderer/bgfx/window.cpp + + src/renderer/bgfx/video/nv12frame.cpp + src/renderer/bgfx/video/yuvframe.cpp ) list(APPEND Impacto_Header src/renderer/bgfx/framebuffer.h @@ -1262,14 +1265,21 @@ if (IMPACTO_RENDERER_BGFX) src/renderer/bgfx/window.h src/renderer/bgfx/shaders/vs_sprite.h + src/renderer/bgfx/shaders/fs_nv12frame.h src/renderer/bgfx/shaders/fs_sprite.h + src/renderer/bgfx/shaders/fs_yuvframe.h + + src/renderer/bgfx/video/nv12frame.h + src/renderer/bgfx/video/yuvframe.h ) set(Bgfx_Vertex_Shaders src/shaders/bgfx/vs_sprite.sc ) set(Bgfx_Fragment_Shaders + src/shaders/bgfx/fs_nv12frame.sc src/shaders/bgfx/fs_sprite.sc + src/shaders/bgfx/fs_yuvframe.sc ) set(Bgfx_Shaders ${Bgfx_Vertex_Shaders} ${Bgfx_Fragment_Shaders}) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index ca347c6a7..1521e4fd0 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -141,7 +141,9 @@ Renderer::Renderer() { } const auto flush = [this]() { Flush(); }; + NV12FrameShader.emplace(vs_sprite_shader, fs_nv12frame_shader, flush); SpriteShader.emplace(vs_sprite_shader, fs_sprite_shader, flush); + YUVFrameShader.emplace(vs_sprite_shader, fs_yuvframe_shader, flush); RectSprite = Sprite(SpriteSheet(1.0f, 1.0f), 0.0f, 0.0f, 1.0f, 1.0f); RectSprite.Sheet.Texture = @@ -397,6 +399,20 @@ void Renderer::FreeTexture(const uint32_t id) { Textures.erase(id); } +Impacto::YUVFrame* Renderer::CreateYUVFrame(const float width, + const float height) { + YUVFrame* const frame = new YUVFrame(); + frame->Init(width, height); + return static_cast(frame); +} + +Impacto::NV12Frame* Renderer::CreateNV12Frame(const float width, + const float height) { + NV12Frame* const frame = new NV12Frame(); + frame->Init(width, height); + return static_cast(frame); +} + void Renderer::Shutdown() { if (bgfx::isValid(IndexBuffer)) bgfx::destroy(IndexBuffer); IndexBuffer.idx = bgfx::kInvalidHandle; @@ -582,6 +598,39 @@ void Renderer::DrawPrimitives( InsertVertices(indices, vertices, ShouldFlip(sheet)); } +void Renderer::DrawVideoTexture(const Impacto::YUVFrame& frame, + const RectF& dest, const glm::vec4 tint, + const bool alphaVideo) { + SetState({ + .ShaderProgram = *YUVFrameShader, + }); + + YUVFrameShader->SubmitUniforms({}, { + .s_luma = *Textures[frame.LumaId], + .s_cb = *Textures[frame.CbId], + .s_cr = *Textures[frame.CrId], + .u_isAlpha = alphaVideo, + }); + + InsertQuad(dest, RectF(0.0f, 0.0f, 1.0f, 1.0f), tint, false); +} + +void Renderer::DrawVideoTexture(const Impacto::NV12Frame& frame, + const RectF& dest, const glm::vec4 tint, + const bool alphaVideo) { + SetState({ + .ShaderProgram = *NV12FrameShader, + }); + + NV12FrameShader->SubmitUniforms({}, { + .s_luma = *Textures[frame.LumaId], + .s_cbCr = *Textures[frame.CbCrId], + .u_isAlpha = alphaVideo, + }); + + InsertQuad(dest, RectF(0.0f, 0.0f, 1.0f, 1.0f), tint, false); +} + void Renderer::InsertQuad(const CornersQuad dest, const CornersQuad uvs, const std::span tints, const bool flipVertically, diff --git a/src/renderer/bgfx/renderer.h b/src/renderer/bgfx/renderer.h index d0e1dedb7..8f411a417 100644 --- a/src/renderer/bgfx/renderer.h +++ b/src/renderer/bgfx/renderer.h @@ -6,6 +6,9 @@ #include "shader.h" #include "texture.h" +#include "video/nv12frame.h" +#include "video/yuvframe.h" + #include #include @@ -42,12 +45,8 @@ class Renderer final : public BaseRenderer { return 0; } void FreeTexture(uint32_t id) override; - YUVFrame* CreateYUVFrame(float width, float height) override { - return nullptr; - } - NV12Frame* CreateNV12Frame(float width, float height) override { - return nullptr; - } + Impacto::YUVFrame* CreateYUVFrame(float width, float height) override; + Impacto::NV12Frame* CreateNV12Frame(float width, float height) override; void DrawSprite(Sprite const& sprite, CornersQuad const& dest, glm::mat4 transformation, std::span tints, @@ -108,10 +107,10 @@ class Renderer final : public BaseRenderer { void DrawMosaic(Sprite const& sprite, CornersQuad dest, float tileSize, glm::mat4 transformation, glm::vec4 tint) override {} - void DrawVideoTexture(YUVFrame const& frame, RectF const& dest, - glm::vec4 tint, bool alphaVideo) override {} - void DrawVideoTexture(NV12Frame const& frame, RectF const& dest, - glm::vec4 tint, bool alphaVideo) override {} + void DrawVideoTexture(Impacto::YUVFrame const& frame, RectF const& dest, + glm::vec4 tint, bool alphaVideo) override; + void DrawVideoTexture(Impacto::NV12Frame const& frame, RectF const& dest, + glm::vec4 tint, bool alphaVideo) override; void DrawSubtitleGlyph(Sprite const& sprite, CornersQuad const& dest, glm::mat4 transformation, glm::vec4 tint) override {} @@ -180,15 +179,22 @@ class Renderer final : public BaseRenderer { bgfx::VertexLayout VertexBufferSpritesLayout; + std::optional< + ShaderProgram> + NV12FrameShader; std::optional< ShaderProgram> SpriteShader; + std::optional< + ShaderProgram> + YUVFrameShader; std::map> Textures; decltype(Textures)::iterator DeclareTexture( std::unique_ptr&& texture); - std::map Textures; + friend class NV12Frame; + friend class YUVFrame; }; } // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shader.h b/src/renderer/bgfx/shader.h index 81a80beda..7a79c1933 100644 --- a/src/renderer/bgfx/shader.h +++ b/src/renderer/bgfx/shader.h @@ -13,7 +13,9 @@ #include "../../log.h" #include "shaders/vs_sprite.h" +#include "shaders/fs_nv12frame.h" #include "shaders/fs_sprite.h" +#include "shaders/fs_yuvframe.h" namespace Impacto::Bgfx { diff --git a/src/renderer/bgfx/shaders/fs_nv12frame.h b/src/renderer/bgfx/shaders/fs_nv12frame.h new file mode 100644 index 000000000..36815102b --- /dev/null +++ b/src/renderer/bgfx/shaders/fs_nv12frame.h @@ -0,0 +1,14 @@ +#pragma once + +#include "../uniform.h" + +namespace Impacto::Bgfx { + +template <> +struct Uniforms { + SamplerUniform<0> s_luma; + SamplerUniform<1> s_cbCr; + bool u_isAlpha = false; +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/shaders/fs_yuvframe.h b/src/renderer/bgfx/shaders/fs_yuvframe.h new file mode 100644 index 000000000..747e2b676 --- /dev/null +++ b/src/renderer/bgfx/shaders/fs_yuvframe.h @@ -0,0 +1,15 @@ +#pragma once + +#include "../uniform.h" + +namespace Impacto::Bgfx { + +template <> +struct Uniforms { + SamplerUniform<0> s_luma; + SamplerUniform<1> s_cb; + SamplerUniform<2> s_cr; + bool u_isAlpha = false; +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/uniform.h b/src/renderer/bgfx/uniform.h index 876ff7c47..96728cddf 100644 --- a/src/renderer/bgfx/uniform.h +++ b/src/renderer/bgfx/uniform.h @@ -93,7 +93,9 @@ enum class VertexShaderType { Sprite, }; enum class FragmentShaderType { + NV12Frame, Sprite, + YUVFrame, }; template @@ -121,10 +123,12 @@ class UniformsState { std::ranges::transform(unorderedHandles, std::inserter(uniqueHandles, uniqueHandles.end()), &bgfx::UniformHandle::idx); - assert(uniqueHandles.size() == UniformCount && - "The number of uniforms defined in shader code is not equal to the " - "number of uniforms defined in the struct. (Some types in the " - "shader code may be illegal!)"); + assert( + uniqueHandles.size() == UniformCount && + "The number of uniforms defined in shader code is not equal to the " + "number of uniforms defined in the struct." + "Tips: Some types in the shader code may be illegal." + "Global constants can also be counted as uniforms on some backends."); constexpr static auto uniformNames = boost::pfr::names_as_array>(); diff --git a/src/renderer/bgfx/video/nv12frame.cpp b/src/renderer/bgfx/video/nv12frame.cpp new file mode 100644 index 000000000..0f976268a --- /dev/null +++ b/src/renderer/bgfx/video/nv12frame.cpp @@ -0,0 +1,56 @@ +#include "nv12frame.h" + +#include "../renderer.h" + +namespace Impacto::Bgfx { + +void NV12Frame::Init(const float width, const float height) { + assert(LumaTexture == nullptr && CbCrTexture == nullptr); + + Width = width; + Height = height; + + LumaTexture = + new MutableTexture(bgfx::TextureFormat::R8, static_cast(width), + static_cast(height)); + CbCrTexture = new MutableTexture(bgfx::TextureFormat::RG8, + static_cast(width) / 2, + static_cast(height) / 2); + + Renderer* const renderer = std::bit_cast(Impacto::Renderer.get()); + LumaId = + renderer->DeclareTexture(std::unique_ptr(LumaTexture))->first; + CbCrId = + renderer->DeclareTexture(std::unique_ptr(CbCrTexture))->first; +} + +void NV12Frame::Submit(const void* const luma, const int lumaStride, + const void* const cbcr, const int cbcrStride) { + assert(LumaTexture != nullptr && CbCrTexture != nullptr); + + LumaTexture->Update( + std::span( + std::bit_cast(luma), + static_cast(lumaStride) * static_cast(Height)), + static_cast(lumaStride)); + CbCrTexture->Update( + std::span( + std::bit_cast(cbcr), + static_cast(cbcrStride) * (static_cast(Height) / 2)), + static_cast(cbcrStride)); +} + +void NV12Frame::Release() { + assert(LumaTexture != nullptr && CbCrTexture != nullptr); + + Impacto::Renderer->FreeTexture(LumaId); + Impacto::Renderer->FreeTexture(CbCrId); + + LumaTexture = nullptr; + CbCrTexture = nullptr; + + LumaId = 0; + CbCrId = 0; +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/video/nv12frame.h b/src/renderer/bgfx/video/nv12frame.h new file mode 100644 index 000000000..342f64630 --- /dev/null +++ b/src/renderer/bgfx/video/nv12frame.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../../nv12frame.h" +#include "../texture.h" + +namespace Impacto::Bgfx { + +class NV12Frame final : public Impacto::NV12Frame { + public: + void Init(float width, float height) override; + + void Submit(const void* luma, int lumaStride, const void* cbcr, + int cbcrStride) override; + void Release() override; + + private: + MutableTexture* LumaTexture = nullptr; + MutableTexture* CbCrTexture = nullptr; +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/video/yuvframe.cpp b/src/renderer/bgfx/video/yuvframe.cpp new file mode 100644 index 000000000..4f03abbf8 --- /dev/null +++ b/src/renderer/bgfx/video/yuvframe.cpp @@ -0,0 +1,65 @@ +#include "yuvframe.h" + +#include "../renderer.h" + +namespace Impacto::Bgfx { + +void YUVFrame::Init(const float width, const float height) { + assert(LumaTexture == nullptr && CbTexture == nullptr && + CrTexture == nullptr); + + Width = width; + Height = height; + + LumaTexture = + new MutableTexture(bgfx::TextureFormat::R8, static_cast(width), + static_cast(height)); + CbTexture = new MutableTexture(bgfx::TextureFormat::R8, + static_cast(width) / 2, + static_cast(height) / 2); + CrTexture = new MutableTexture(bgfx::TextureFormat::R8, + static_cast(width) / 2, + static_cast(height) / 2); + + Renderer* const renderer = std::bit_cast(Impacto::Renderer.get()); + LumaId = + renderer->DeclareTexture(std::unique_ptr(LumaTexture))->first; + CbId = renderer->DeclareTexture(std::unique_ptr(CbTexture))->first; + CrId = renderer->DeclareTexture(std::unique_ptr(CrTexture))->first; +} + +void YUVFrame::Submit(const void* luma, const void* cb, const void* cr) { + assert(LumaTexture != nullptr && CbTexture != nullptr && + CrTexture != nullptr); + + size_t dataSize = static_cast(Width) * static_cast(Height); + + LumaTexture->Update( + std::span(std::bit_cast(luma), dataSize), + static_cast(Width)); + CbTexture->Update( + std::span(std::bit_cast(cb), dataSize / 4), + static_cast(Width) / 2); + CrTexture->Update( + std::span(std::bit_cast(cr), dataSize / 4), + static_cast(Width) / 2); +} + +void YUVFrame::Release() { + assert(LumaTexture != nullptr && CbTexture != nullptr && + CrTexture != nullptr); + + Impacto::Renderer->FreeTexture(LumaId); + Impacto::Renderer->FreeTexture(CbId); + Impacto::Renderer->FreeTexture(CrId); + + LumaTexture = nullptr; + CbTexture = nullptr; + CrTexture = nullptr; + + LumaId = 0; + CbId = 0; + CrId = 0; +} + +} // namespace Impacto::Bgfx diff --git a/src/renderer/bgfx/video/yuvframe.h b/src/renderer/bgfx/video/yuvframe.h new file mode 100644 index 000000000..dc52fa988 --- /dev/null +++ b/src/renderer/bgfx/video/yuvframe.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../../yuvframe.h" +#include "../texture.h" + +namespace Impacto::Bgfx { + +class YUVFrame final : public Impacto::YUVFrame { + public: + void Init(float width, float height) override; + + void Submit(const void* luma, const void* cb, const void* cr) override; + void Release() override; + + private: + MutableTexture* LumaTexture = nullptr; + MutableTexture* CbTexture = nullptr; + MutableTexture* CrTexture = nullptr; +}; + +} // namespace Impacto::Bgfx diff --git a/src/renderer/nv12frame.h b/src/renderer/nv12frame.h index 116e3b437..0204354bb 100644 --- a/src/renderer/nv12frame.h +++ b/src/renderer/nv12frame.h @@ -8,8 +8,9 @@ class NV12Frame { public: float Width; float Height; - uint32_t LumaId; - uint32_t CbCrId; + + uint32_t LumaId = 0; + uint32_t CbCrId = 0; virtual void Init(float width, float height) = 0; diff --git a/src/renderer/yuvframe.h b/src/renderer/yuvframe.h index 256de86f3..c18ead365 100644 --- a/src/renderer/yuvframe.h +++ b/src/renderer/yuvframe.h @@ -8,9 +8,10 @@ class YUVFrame { public: float Width; float Height; - uint32_t LumaId; - uint32_t CbId; - uint32_t CrId; + + uint32_t LumaId = 0; + uint32_t CbId = 0; + uint32_t CrId = 0; virtual void Init(float width, float height) = 0; diff --git a/src/shaders/bgfx/fs_nv12frame.sc b/src/shaders/bgfx/fs_nv12frame.sc new file mode 100644 index 000000000..0ba59edc4 --- /dev/null +++ b/src/shaders/bgfx/fs_nv12frame.sc @@ -0,0 +1,37 @@ +$input v_texcoord0, v_color0 + +#include + +SAMPLER2D(s_luma, 0); +SAMPLER2D(s_cbCr, 1); + +uniform vec4 u_isAlpha; + +vec4 getRgba(vec2 texUv) { + mat4 yuv_to_rgb_rec601 = mtxFromRows( + vec4(1.16438, 0.00000, 1.59603, -0.87079), + vec4(1.16438, -0.39176, -0.81297, 0.52959), + vec4(1.16438, 2.01723, 0.00000, -1.08139), + vec4(0, 0, 0, 1) + ); + + return mul( + yuv_to_rgb_rec601, + vec4( + texture2D(s_luma, texUv).r, + texture2D(s_cbCr, texUv).rg, + 1.0 + ) + ); +} + +void main() { + if (u_isAlpha.x != 0.0) { + gl_FragColor.rgb = getRgba(vec2(v_texcoord0.x, v_texcoord0.y / 2.0)).rgb; + gl_FragColor.a = getRgba(vec2(v_texcoord0.x, v_texcoord0.y / 2.0 + 0.5)).a; + } else { + gl_FragColor = getRgba(v_texcoord0); + } + + gl_FragColor *= v_color0; +} diff --git a/src/shaders/bgfx/fs_yuvframe.sc b/src/shaders/bgfx/fs_yuvframe.sc new file mode 100644 index 000000000..56973207f --- /dev/null +++ b/src/shaders/bgfx/fs_yuvframe.sc @@ -0,0 +1,39 @@ +$input v_texcoord0, v_color0 + +#include + +SAMPLER2D(s_luma, 0); +SAMPLER2D(s_cb, 1); +SAMPLER2D(s_cr, 2); + +uniform vec4 u_isAlpha; + +vec4 getRgba(vec2 texUv) { + mat4 yuv_to_rgb_rec601 = mtxFromRows( + vec4(1.16438, 0.00000, 1.59603, -0.87079), + vec4(1.16438, -0.39176, -0.81297, 0.52959), + vec4(1.16438, 2.01723, 0.00000, -1.08139), + vec4(0, 0, 0, 1) + ); + + return mul( + yuv_to_rgb_rec601, + vec4( + texture2D(s_luma, texUv).r, + texture2D(s_cb, texUv).r, + texture2D(s_cr, texUv).r, + 1.0 + ) + ); +} + +void main() { + if (u_isAlpha.x != 0.0) { + gl_FragColor = getRgba(vec2(v_texcoord0.x, v_texcoord0.y / 2.0)); + gl_FragColor.a = getRgba(vec2(v_texcoord0.x, v_texcoord0.y / 2.0 + 0.5)).r; + } else { + gl_FragColor = getRgba(v_texcoord0); + } + + gl_FragColor *= v_color0; +} diff --git a/src/shaders/bgfx/vs_sprite.sc b/src/shaders/bgfx/vs_sprite.sc index 5d5990585..dd083ccfa 100644 --- a/src/shaders/bgfx/vs_sprite.sc +++ b/src/shaders/bgfx/vs_sprite.sc @@ -4,7 +4,7 @@ $output v_texcoord0, v_color0 #include void main() { - gl_Position = mul(u_proj, vec4(a_position, 0.0f, 1.0f)); + gl_Position = mul(u_modelViewProj, vec4(a_position, 0.0f, 1.0f)); v_texcoord0 = a_texcoord0; v_color0 = a_color0; From e3db740102ab13f94ea25926001af6a6ce7d50d6 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Thu, 17 Sep 2026 01:28:08 +0200 Subject: [PATCH 34/60] Turn freeing the null-texture into a noop --- src/renderer/bgfx/renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer/bgfx/renderer.cpp b/src/renderer/bgfx/renderer.cpp index 1521e4fd0..6cb41f296 100644 --- a/src/renderer/bgfx/renderer.cpp +++ b/src/renderer/bgfx/renderer.cpp @@ -395,6 +395,7 @@ decltype(Renderer::Textures)::iterator Renderer::DeclareTexture( } void Renderer::FreeTexture(const uint32_t id) { + if (id == 0) return; assert(Textures.contains(id)); Textures.erase(id); } From a03d0e293f06e4954e175ede831ded9bf5bfe05e Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Thu, 17 Sep 2026 01:28:40 +0200 Subject: [PATCH 35/60] Use std::optional for nullable sprites instead of 'nullsprites' --- src/games/cc/sysmesbox.cpp | 34 ++++--- src/games/cc/titlemenu.cpp | 21 ++--- src/games/cclcc/moviemenu.cpp | 2 +- src/games/cclcc/musicmenu.cpp | 6 +- src/games/cclcc/systemmenu.cpp | 6 +- src/games/cclcc/titlemenu.cpp | 25 +++--- src/games/chlcc/sysmesbox.cpp | 6 +- src/games/chlcc/systemmenu.cpp | 2 +- src/games/darling/sysmesbox.cpp | 5 +- src/games/mo6tw/albummenu.cpp | 9 +- src/games/mo6tw/clearlistmenu.cpp | 6 +- src/games/mo6tw/moviemenu.cpp | 6 +- src/games/mo6tw/musicmenu.cpp | 12 ++- src/games/mo6tw/musicmenu.h | 1 - src/games/mo6tw/savemenu.cpp | 4 +- src/games/mo6tw/sysmesbox.cpp | 5 +- src/games/mo6tw/titlemenu.cpp | 89 +++++++++---------- src/games/mo8/optionsmenu.cpp | 38 ++++---- src/games/mo8/savemenu.cpp | 6 +- src/games/mo8/systemmenu.cpp | 11 +-- src/games/mo8/titlemenu.cpp | 3 - src/games/rne/sysmesbox.cpp | 48 +++++----- src/games/rne/systemmenu.cpp | 7 +- src/hud/dialoguebox.cpp | 20 ++--- src/profile/ui/selectionmenu.cpp | 8 +- src/profile/ui/selectionmenu.h | 4 +- src/ui/selectionmenu.cpp | 7 +- src/ui/widgets/button.cpp | 43 +++++---- src/ui/widgets/button.h | 15 ++-- src/ui/widgets/cc/titlebutton.cpp | 27 +++--- src/ui/widgets/cc/titlebutton.h | 4 +- src/ui/widgets/cclcc/librarymenubutton.h | 6 +- src/ui/widgets/cclcc/saveentrybutton.cpp | 6 +- src/ui/widgets/cclcc/sysmenubutton.cpp | 8 +- src/ui/widgets/cclcc/sysmenubutton.h | 6 +- src/ui/widgets/cclcc/tipsentrybutton.cpp | 8 +- src/ui/widgets/cclcc/tipstabgroup.cpp | 5 +- src/ui/widgets/cclcc/titlebutton.cpp | 27 +++--- src/ui/widgets/cclcc/titlebutton.h | 4 +- src/ui/widgets/chlcc/albumthumbnailbutton.cpp | 4 +- src/ui/widgets/chlcc/moviemenuentrybutton.cpp | 4 +- .../widgets/chlcc/systemmenuentrybutton.cpp | 15 ++-- src/ui/widgets/chlcc/systemmenuentrybutton.h | 5 +- src/ui/widgets/chlcc/systemmessagebutton.cpp | 23 +++-- src/ui/widgets/chlcc/systemmessagebutton.h | 6 +- src/ui/widgets/chlcc/tipsentrybutton.cpp | 2 +- src/ui/widgets/chlcc/titlebutton.cpp | 14 +-- src/ui/widgets/chlcc/trackselectbutton.cpp | 9 +- src/ui/widgets/label.cpp | 18 ++-- src/ui/widgets/label.h | 6 +- src/ui/widgets/mo6tw/actorsvoicebutton.cpp | 10 +-- src/ui/widgets/mo6tw/albumcharacterbutton.cpp | 11 +-- src/ui/widgets/mo6tw/imagethumbnailbutton.cpp | 36 ++++---- src/ui/widgets/mo6tw/imagethumbnailbutton.h | 19 ++-- src/ui/widgets/mo6tw/saveentrybutton.cpp | 9 +- src/ui/widgets/mo6tw/saveentrybutton.h | 5 +- src/ui/widgets/mo6tw/scenelistentry.cpp | 2 +- src/ui/widgets/mo6tw/tipsentrybutton.cpp | 6 +- src/ui/widgets/mo6tw/titlebutton.cpp | 17 ++-- src/ui/widgets/mo6tw/titlebutton.h | 5 +- src/ui/widgets/optiongroup.cpp | 9 +- src/ui/widgets/optiongroup.h | 4 +- src/ui/widgets/rne/sysmenubutton.cpp | 13 ++- src/ui/widgets/rne/sysmenubutton.h | 5 +- src/ui/widgets/scrollbar.cpp | 67 ++++++++------ src/ui/widgets/scrollbar.h | 16 ++-- src/ui/widgets/toggle.cpp | 20 +++-- src/ui/widgets/toggle.h | 8 +- 68 files changed, 457 insertions(+), 461 deletions(-) diff --git a/src/games/cc/sysmesbox.cpp b/src/games/cc/sysmesbox.cpp index 74795c755..8c98637d5 100644 --- a/src/games/cc/sysmesbox.cpp +++ b/src/games/cc/sysmesbox.cpp @@ -31,9 +31,6 @@ void SysMesBox::Show() { MessageItems = std::make_unique(this); ChoiceItems = std::make_unique(this); - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - auto onClick = [this](auto* btn) { return ChoiceItemOnClick(btn); }; float textBeginY = (TextMiddleY - TextMarginY * MessageCount) / 2.0f; @@ -55,7 +52,7 @@ void SysMesBox::Show() { if (ChoiceCount == 1) { WidgetOK = - new Button(0, ButtonOK, ButtonOKHighlighted, nullSprite, + new Button(0, ButtonOK, ButtonOKHighlighted, std::nullopt, glm::vec2(ButtonOKCenterPosX - (ButtonOK.Bounds.Width / 2), ButtonOKCenterPosY - (ButtonOK.Bounds.Height / 2)), ButtonOkHoverBounds); @@ -64,14 +61,14 @@ void SysMesBox::Show() { } else if (ChoiceCount == 2) { WidgetYes = new Button( - 0, ButtonYes, ButtonYesHighlighted, nullSprite, + 0, ButtonYes, ButtonYesHighlighted, std::nullopt, glm::vec2(ButtonYesCenterPosX - (ButtonYes.Bounds.Width / 2), ButtonYesCenterPosY - (ButtonYes.Bounds.Height / 2)), ButtonYesHoverBounds); WidgetYes->OnClickHandler = onClick; ChoiceItems->Add(WidgetYes, FDIR_RIGHT); WidgetNo = - new Button(1, ButtonNo, ButtonNoHighlighted, nullSprite, + new Button(1, ButtonNo, ButtonNoHighlighted, std::nullopt, glm::vec2(ButtonNoCenterPosX - (ButtonNo.Bounds.Width / 2), ButtonNoCenterPosY - (ButtonNo.Bounds.Height / 2)), ButtonNoHoverBounds); @@ -146,12 +143,12 @@ void SysMesBox::Update(float dt) { ButtonYesAnimationProgressEnd); float scaleYes = ButtonScaleMax - (offsetProgress * ButtonYesNoScaleMultiplier); - WidgetYes->NormalSprite.BaseScale = glm::vec2(scaleYes); - WidgetYes->FocusedSprite.BaseScale = glm::vec2(scaleYes); + WidgetYes->NormalSprite->BaseScale = glm::vec2(scaleYes); + WidgetYes->FocusedSprite->BaseScale = glm::vec2(scaleYes); WidgetYes->MoveTo(glm::vec2( - ButtonYesCenterPosX - (WidgetYes->NormalSprite.ScaledWidth() * 0.5f), + ButtonYesCenterPosX - (WidgetYes->NormalSprite->ScaledWidth() * 0.5f), ButtonYesCenterPosY - - (WidgetYes->NormalSprite.ScaledHeight() * 0.5f))); + (WidgetYes->NormalSprite->ScaledHeight() * 0.5f))); WidgetYes->Tint = glm::vec4(1.0f, 1.0f, 1.0f, offsetProgress / ButtonYesNoAlphaDivider); @@ -160,12 +157,12 @@ void SysMesBox::Update(float dt) { offsetProgress = animationProgress - ButtonNoAnimationProgressOffset; float scaleNo = ButtonScaleMax - (offsetProgress * ButtonYesNoScaleMultiplier); - WidgetNo->NormalSprite.BaseScale = glm::vec2(scaleNo); - WidgetNo->FocusedSprite.BaseScale = glm::vec2(scaleNo); + WidgetNo->NormalSprite->BaseScale = glm::vec2(scaleNo); + WidgetNo->FocusedSprite->BaseScale = glm::vec2(scaleNo); WidgetNo->MoveTo(glm::vec2( - ButtonNoCenterPosX - (WidgetNo->NormalSprite.ScaledWidth() * 0.5f), + ButtonNoCenterPosX - (WidgetNo->NormalSprite->ScaledWidth() * 0.5f), ButtonNoCenterPosY - - (WidgetNo->NormalSprite.ScaledHeight() * 0.5f))); + (WidgetNo->NormalSprite->ScaledHeight() * 0.5f))); WidgetNo->Tint = glm::vec4(1.0f, 1.0f, 1.0f, offsetProgress / ButtonYesNoAlphaDivider); } else { @@ -176,11 +173,12 @@ void SysMesBox::Update(float dt) { (animationProgress - AnimationProgressWidgetsStartOffset); float scaleOk = ButtonScaleMax - (offsetProgress * ButtonOKScaleMultiplier); - WidgetOK->NormalSprite.BaseScale = glm::vec2(scaleOk); - WidgetOK->FocusedSprite.BaseScale = glm::vec2(scaleOk); + WidgetOK->NormalSprite->BaseScale = glm::vec2(scaleOk); + WidgetOK->FocusedSprite->BaseScale = glm::vec2(scaleOk); WidgetOK->MoveTo(glm::vec2( - ButtonOKCenterPosX - (WidgetOK->NormalSprite.ScaledWidth() * 0.5f), - ButtonOKCenterPosY - (WidgetOK->NormalSprite.ScaledHeight() * 0.5f))); + ButtonOKCenterPosX - (WidgetOK->NormalSprite->ScaledWidth() * 0.5f), + ButtonOKCenterPosY - + (WidgetOK->NormalSprite->ScaledHeight() * 0.5f))); WidgetOK->Tint = glm::vec4(1.0f, 1.0f, 1.0f, WidgetsAlphaMultiplier * offsetProgress); } diff --git a/src/games/cc/titlemenu.cpp b/src/games/cc/titlemenu.cpp index 838f28f97..019a6baec 100644 --- a/src/games/cc/titlemenu.cpp +++ b/src/games/cc/titlemenu.cpp @@ -65,9 +65,6 @@ TitleMenu::TitleMenu() { }; auto extraOnClick = [this](auto* btn) { return ExtraButtonOnClick(btn); }; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - // NewGame menu button NewGame = new TitleButton( 0, MenuEntriesSprites[0], MenuEntriesHSprites[0], ItemHighlightSprite, @@ -109,7 +106,7 @@ TitleMenu::TitleMenu() { MainItems->Add(Help, FDIR_DOWN); // Load secondary Continue menu button - Load = new TitleButton(10, LoadSprite, LoadHighlightSprite, nullSprite, + Load = new TitleButton(10, LoadSprite, LoadHighlightSprite, std::nullopt, glm::vec2(((SecondaryFirstItemHighlightOffsetX)) + SecondaryFirstItemHighlightOffsetX, (ItemYBase + (2 * ItemPadding)))); @@ -118,17 +115,17 @@ TitleMenu::TitleMenu() { ContinueItems->Add(Load, FDIR_RIGHT); // QuickLoad secondary Continue menu button - QuickLoad = - new TitleButton(11, QuickLoadSprite, QuickLoadHighlightSprite, nullSprite, - glm::vec2(((SecondarySecondItemHighlightOffsetX)) + - SecondarySecondItemHighlightOffsetX, - (ItemYBase + (2 * ItemPadding)))); + QuickLoad = new TitleButton( + 11, QuickLoadSprite, QuickLoadHighlightSprite, std::nullopt, + glm::vec2(((SecondarySecondItemHighlightOffsetX)) + + SecondarySecondItemHighlightOffsetX, + (ItemYBase + (2 * ItemPadding)))); QuickLoad->OnClickHandler = onClick; QuickLoad->IsSubButton = true; ContinueItems->Add(QuickLoad, FDIR_RIGHT); // Tips secondary Extra menu button - Tips = new TitleButton(30, TipsSprite, TipsHighlightSprite, nullSprite, + Tips = new TitleButton(30, TipsSprite, TipsHighlightSprite, std::nullopt, glm::vec2(((SecondaryFirstItemHighlightOffsetX)) + SecondaryFirstItemHighlightOffsetX, (ItemYBase + (3 * ItemPadding)))); @@ -138,7 +135,7 @@ TitleMenu::TitleMenu() { // Library secondary Extra menu button Library = - new TitleButton(31, LibrarySprite, LibraryHighlightSprite, nullSprite, + new TitleButton(31, LibrarySprite, LibraryHighlightSprite, std::nullopt, glm::vec2(((SecondarySecondItemHighlightOffsetX)) + SecondarySecondItemHighlightOffsetX, (ItemYBase + (3 * ItemPadding)))); @@ -148,7 +145,7 @@ TitleMenu::TitleMenu() { // EndingList secondary Extra menu button EndingList = new TitleButton( - 32, EndingListSprite, EndingListHighlightSprite, nullSprite, + 32, EndingListSprite, EndingListHighlightSprite, std::nullopt, glm::vec2(((SecondaryThirdItemHighlightOffsetX)) + SecondaryThirdItemHighlightOffsetX, (ItemYBase + (3 * ItemPadding)))); diff --git a/src/games/cclcc/moviemenu.cpp b/src/games/cclcc/moviemenu.cpp index 2913c3151..74e381395 100644 --- a/src/games/cclcc/moviemenu.cpp +++ b/src/games/cclcc/moviemenu.cpp @@ -43,7 +43,7 @@ MovieMenu::MovieMenu() : LibrarySubmenu() { Audio::Channels[Audio::AC_BGM0]->Stop(0.0f); }; auto disk = new Widgets::Button(static_cast(i), diskSprite, - diskHighlightSprite, Sprite(), + diskHighlightSprite, std::nullopt, MovieDiskDisplayPositions[i]); disk->OnClickHandler = movieOnclick; MainItems.Add(disk, FDIR_RIGHT); diff --git a/src/games/cclcc/musicmenu.cpp b/src/games/cclcc/musicmenu.cpp index fd08a8805..7bf485896 100644 --- a/src/games/cclcc/musicmenu.cpp +++ b/src/games/cclcc/musicmenu.cpp @@ -121,14 +121,14 @@ void MusicTrackButton::Render() { Renderer->DrawSprite( MusicButtonPlayingSprite, MusicButtonPlayingDispOffset + glm::vec2(Bounds.X, Bounds.Y), Tint); - Renderer->DrawSprite(FocusedSprite, glm::vec2(Bounds.X + 113, Bounds.Y), + Renderer->DrawSprite(*FocusedSprite, glm::vec2(Bounds.X + 113, Bounds.Y), Tint); } else { Profile::Dialogue::DialogueFont->DrawProcessedText(NumberText, Tint.a); } if (HasFocus) { - Renderer->DrawSprite(HighlightSprite, glm::vec2(Bounds.X + 113, Bounds.Y), - Tint); + Renderer->DrawSprite(*HighlightSprite, + glm::vec2(Bounds.X + 113, Bounds.Y), Tint); } if (IsLocked) { Profile::Dialogue::DialogueFont->DrawProcessedText(LockedText, Tint.a); diff --git a/src/games/cclcc/systemmenu.cpp b/src/games/cclcc/systemmenu.cpp index 67f43c6eb..ffe2e45df 100644 --- a/src/games/cclcc/systemmenu.cpp +++ b/src/games/cclcc/systemmenu.cpp @@ -74,9 +74,9 @@ SystemMenu::SystemMenu() : CommonMenu(FadeAnimation) { ScreenCap.Bounds.SetSize(viewport.GetSize()); for (int i = 0; i < MenuEntriesNum; i++) { - SysMenuButton* menuButton = new SysMenuButton( - i, MenuEntriesSprites[i], Sprite(), MenuEntriesHSprites[i], - MenuEntriesPositions[i], MenuEntriesButtonBounds[i]); + SysMenuButton* menuButton = + new SysMenuButton(i, MenuEntriesSprites[i], MenuEntriesHSprites[i], + MenuEntriesPositions[i], MenuEntriesButtonBounds[i]); menuButton->OnClickHandler = onClick; MainItems->Add(menuButton, FDIR_DOWN); diff --git a/src/games/cclcc/titlemenu.cpp b/src/games/cclcc/titlemenu.cpp index 73483d643..eb984e759 100644 --- a/src/games/cclcc/titlemenu.cpp +++ b/src/games/cclcc/titlemenu.cpp @@ -165,9 +165,6 @@ TitleMenu::TitleMenu() { ExtraItems = new Widgets::Group(this); ExtraItems->WrapFocus = false; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - MenuLabel = new Widgets::Label(MenuSprite, MenuPos); auto onClick = [this](Widgets::Button* target) { @@ -244,36 +241,36 @@ TitleMenu::TitleMenu() { } // Load secondary Continue menu button - Load = - new TitleButton(LoadButtonId, LoadSprite, LoadHighlightSprite, nullSprite, - glm::vec2(SecondaryFirstItemHighlightOffsetX, - (ItemYBase + (2 * ItemPadding)))); + Load = new TitleButton(LoadButtonId, LoadSprite, LoadHighlightSprite, + std::nullopt, + glm::vec2(SecondaryFirstItemHighlightOffsetX, + (ItemYBase + (2 * ItemPadding)))); setupBtn(Load, onClick, ContinueItems, FDIR_RIGHT); // QuickLoad secondary Continue menu button QuickLoad = new TitleButton(QLoadButtonId, QuickLoadSprite, - QuickLoadHighlightSprite, nullSprite, + QuickLoadHighlightSprite, std::nullopt, glm::vec2(SecondarySecondItemHighlightOffsetX, (ItemYBase + (2 * ItemPadding)))); setupBtn(QuickLoad, onClick, ContinueItems, FDIR_RIGHT); // Tips secondary Extra menu button - Tips = - new TitleButton(TipsButtonId, TipsSprite, TipsHighlightSprite, nullSprite, - glm::vec2(SecondaryFirstItemHighlightOffsetX, - (ItemYBase + (3 * ItemPadding)))); + Tips = new TitleButton(TipsButtonId, TipsSprite, TipsHighlightSprite, + std::nullopt, + glm::vec2(SecondaryFirstItemHighlightOffsetX, + (ItemYBase + (3 * ItemPadding)))); setupBtn(Tips, onClick, ExtraItems, FDIR_RIGHT); // Library secondary Extra menu button Library = new TitleButton(LibraryButtonId, LibrarySprite, - LibraryHighlightSprite, nullSprite, + LibraryHighlightSprite, std::nullopt, glm::vec2(SecondarySecondItemHighlightOffsetX, (ItemYBase + (3 * ItemPadding)))); setupBtn(Library, onClick, ExtraItems, FDIR_RIGHT); // EndingList secondary Extra menu button EndingList = new TitleButton(EndingListButtonId, EndingListSprite, - EndingListHighlightSprite, nullSprite, + EndingListHighlightSprite, std::nullopt, glm::vec2(SecondaryThirdItemHighlightOffsetX, (ItemYBase + (3 * ItemPadding)))); setupBtn(EndingList, onClick, ExtraItems, FDIR_RIGHT); diff --git a/src/games/chlcc/sysmesbox.cpp b/src/games/chlcc/sysmesbox.cpp index a24486784..c039cad92 100644 --- a/src/games/chlcc/sysmesbox.cpp +++ b/src/games/chlcc/sysmesbox.cpp @@ -32,9 +32,6 @@ void SysMesBox::Show() { MessageItems = std::make_unique(this); ChoiceItems = std::make_unique(this); - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - auto onClick = [this](auto* btn) { return ChoiceItemOnClick(btn); }; float diff = 0.0f; @@ -72,8 +69,7 @@ void SysMesBox::Show() { } Button* choice = new SystemMessageButton( - i, nullSprite, nullSprite, SelectionLeftPart, SelectionMiddlePart, - SelectionRightPart, + i, SelectionLeftPart, SelectionMiddlePart, SelectionRightPart, glm::vec2(Choices[i][0].DestRect.X, Choices[i][0].DestRect.Y)); choice->HighlightOffset = glm::vec2(HighlightXOffset, HighlightYOffset); diff --git a/src/games/chlcc/systemmenu.cpp b/src/games/chlcc/systemmenu.cpp index 539669c62..3f7f803ed 100644 --- a/src/games/chlcc/systemmenu.cpp +++ b/src/games/chlcc/systemmenu.cpp @@ -57,7 +57,7 @@ SystemMenu::SystemMenu() : CommonMenu(false) { for (int i = 0; i < MenuEntriesNum; i++) { SystemMenuEntryButton* menuButton = new SystemMenuEntryButton( i, MenuEntriesSprites[i], MenuEntriesSprites[i], - RgbIntToFloat(FocusTint), Sprite(), MenuEntriesPositions[i], + RgbIntToFloat(FocusTint), MenuEntriesPositions[i], RectF( MenuEntriesPositions[i].x - 30, (i + 1) * MenuSelectionDotMultiplier + MenuSelectionPosition.y - 14, diff --git a/src/games/darling/sysmesbox.cpp b/src/games/darling/sysmesbox.cpp index fe7a1465b..d4e195a51 100644 --- a/src/games/darling/sysmesbox.cpp +++ b/src/games/darling/sysmesbox.cpp @@ -25,9 +25,6 @@ void SysMesBox::Show() { MessageItems = std::make_unique(this); ChoiceItems = std::make_unique(this); - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - auto onClick = [this](auto* btn) { return ChoiceItemOnClick(btn); }; float diff = 0.0f; @@ -72,7 +69,7 @@ void SysMesBox::Show() { } Button* choice = new Button( - i, nullSprite, nullSprite, SelectionHighlight, + i, std::nullopt, std::nullopt, SelectionHighlight, glm::vec2(Choices[i][0].DestRect.X, Choices[i][0].DestRect.Y)); choice->SetText(Choices[i], ChoiceWidths[i], diff --git a/src/games/mo6tw/albummenu.cpp b/src/games/mo6tw/albummenu.cpp index a7c40ff53..96c8c11fb 100644 --- a/src/games/mo6tw/albummenu.cpp +++ b/src/games/mo6tw/albummenu.cpp @@ -104,16 +104,13 @@ AlbumMenu::AlbumMenu() { Arrows = new Group(this); Arrows->FocusLock = false; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - ArrowUpButton = new Button(0, ArrowUp, ArrowUp, nullSprite, ArrowUpPosition); - ArrowUpButton->DisabledSprite = nullSprite; + ArrowUpButton = + new Button(0, ArrowUp, ArrowUp, std::nullopt, ArrowUpPosition); ArrowUpButton->OnClickHandler = [this](auto* btn) { return ArrowUpOnClick(btn); }; ArrowDownButton = - new Button(1, ArrowDown, ArrowDown, nullSprite, ArrowDownPosition); - ArrowDownButton->DisabledSprite = nullSprite; + new Button(1, ArrowDown, ArrowDown, std::nullopt, ArrowDownPosition); ArrowDownButton->OnClickHandler = [this](auto* btn) { return ArrowDownOnClick(btn); }; diff --git a/src/games/mo6tw/clearlistmenu.cpp b/src/games/mo6tw/clearlistmenu.cpp index 8f85c70ef..ab49352a5 100644 --- a/src/games/mo6tw/clearlistmenu.cpp +++ b/src/games/mo6tw/clearlistmenu.cpp @@ -51,15 +51,13 @@ ClearListMenu::ClearListMenu() { Arrows = new Group(this); Arrows->FocusLock = false; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); auto arrowLeft = - new Button(0, ArrowLeft, ArrowLeft, nullSprite, ArrowLeftPosition); + new Button(0, ArrowLeft, ArrowLeft, std::nullopt, ArrowLeftPosition); arrowLeft->OnClickHandler = [this](auto* btn) { return ArrowLeftOnClick(btn); }; auto arrowRight = - new Button(1, ArrowRight, ArrowRight, nullSprite, ArrowRightPosition); + new Button(1, ArrowRight, ArrowRight, std::nullopt, ArrowRightPosition); arrowRight->OnClickHandler = [this](auto* btn) { return ArrowRightOnClick(btn); }; diff --git a/src/games/mo6tw/moviemenu.cpp b/src/games/mo6tw/moviemenu.cpp index 002aa33dc..cd4fe8acf 100644 --- a/src/games/mo6tw/moviemenu.cpp +++ b/src/games/mo6tw/moviemenu.cpp @@ -35,10 +35,8 @@ MovieMenu::MovieMenu() { auto pos = InitialItemPosition; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); auto firstOp = new Widgets::MO6TW::ImageThumbnailButton( - 0, FirstOPTopPartSprite, FirstOPBottomPartSprite, nullSprite, + 0, FirstOPTopPartSprite, FirstOPBottomPartSprite, std::nullopt, SelectionHighlightTopLeft, SelectionHighlightTopRight, SelectionHighlightBottomLeft, SelectionHighlightBottomRight, pos); firstOp->OnClickHandler = onClick; @@ -47,7 +45,7 @@ MovieMenu::MovieMenu() { pos.x += ItemOffset.x; auto secondOp = new Widgets::MO6TW::ImageThumbnailButton( - 1, SecondOPTopPartSprite, SecondOPBottomPartSprite, nullSprite, + 1, SecondOPTopPartSprite, SecondOPBottomPartSprite, std::nullopt, SelectionHighlightTopLeft, SelectionHighlightTopRight, SelectionHighlightBottomLeft, SelectionHighlightBottomRight, pos); secondOp->OnClickHandler = onClick; diff --git a/src/games/mo6tw/musicmenu.cpp b/src/games/mo6tw/musicmenu.cpp index 4e7b29872..f58a2ea1a 100644 --- a/src/games/mo6tw/musicmenu.cpp +++ b/src/games/mo6tw/musicmenu.cpp @@ -43,11 +43,9 @@ MusicMenu::MusicMenu() { BackgroundItems->Add(new Label(ItemsWindow, ItemsWindowPosition)); BackgroundItems->Add(new Label(PlaybackWindow, PlaybackWindowPosition)); - NullSprite = Sprite(); - NullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - Thumbnail = new Label(NullSprite, ThumbnailPosition); + Thumbnail = new Label(std::nullopt, ThumbnailPosition); BackgroundItems->Add(Thumbnail); - CurrentlyPlaying = new Label(NullSprite, CurrentlyPlayingLabelPosition); + CurrentlyPlaying = new Label(std::nullopt, CurrentlyPlayingLabelPosition); BackgroundItems->Add(CurrentlyPlaying); PlaybackModeLabel = new Label(PlaybackModeLabels[PlaybackMode], PlaybackModeLabelPosition); @@ -83,7 +81,7 @@ MusicMenu::MusicMenu() { pos = TimerInitialPosition; for (int i = 0; i < 8; i++) { - Timer->Add(new Label(NullSprite, pos)); + Timer->Add(new Label(std::nullopt, pos)); pos += TimerMargin; } } @@ -240,8 +238,8 @@ void MusicMenu::SwitchToTrack(int id) { CurrentlyPlayingTrackId = id; if (id == -1) { Audio::Channels[Audio::AC_BGM0]->Stop(0.5f); - Thumbnail->SetSprite(NullSprite); - CurrentlyPlaying->SetSprite(NullSprite); + Thumbnail->SetSprite(std::nullopt); + CurrentlyPlaying->SetSprite(std::nullopt); Timer->Hide(); return; } diff --git a/src/games/mo6tw/musicmenu.h b/src/games/mo6tw/musicmenu.h index f54aba358..399729662 100644 --- a/src/games/mo6tw/musicmenu.h +++ b/src/games/mo6tw/musicmenu.h @@ -41,7 +41,6 @@ class MusicMenu : public Menu { Widgets::Label* CurrentlyPlaying; Widgets::Label* PlaybackModeLabel; Animation FadeAnimation; - Sprite NullSprite; float MusicListY; MusicPlaybackMode PlaybackMode = MPM_One; diff --git a/src/games/mo6tw/savemenu.cpp b/src/games/mo6tw/savemenu.cpp index 60e75eb1e..3a327af3c 100644 --- a/src/games/mo6tw/savemenu.cpp +++ b/src/games/mo6tw/savemenu.cpp @@ -55,8 +55,6 @@ void SaveMenu::Show() { Sprite entrySprite; Sprite entryHSprite; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); switch (*ActiveMenuType) { case SaveMenuPageType::QuickLoad: @@ -76,7 +74,7 @@ void SaveMenu::Show() { for (int i = 0; i < RowsPerPage; i++) { for (int j = 0; j < EntriesPerRow; j++) { SaveEntryButton* saveEntryButton = - new SaveEntryButton(id, entrySprite, entryHSprite, nullSprite, + new SaveEntryButton(id, entrySprite, entryHSprite, glm::vec2(EntryStartX + (j * EntryXPadding), EntryStartY + (i * EntryYPadding))); diff --git a/src/games/mo6tw/sysmesbox.cpp b/src/games/mo6tw/sysmesbox.cpp index 3bba0b996..d039dcb98 100644 --- a/src/games/mo6tw/sysmesbox.cpp +++ b/src/games/mo6tw/sysmesbox.cpp @@ -25,9 +25,6 @@ void SysMesBox::Show() { MessageItems = std::make_unique(this); ChoiceItems = std::make_unique(this); - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - auto onClick = [this](auto* btn) { return ChoiceItemOnClick(btn); }; float diff = 0.0f; @@ -72,7 +69,7 @@ void SysMesBox::Show() { } Button* choice = new Button( - i, nullSprite, nullSprite, SelectionHighlight, + i, std::nullopt, std::nullopt, SelectionHighlight, glm::vec2(Choices[i][0].DestRect.X, Choices[i][0].DestRect.Y)); choice->SetText(Choices[i], ChoiceWidths[i], diff --git a/src/games/mo6tw/titlemenu.cpp b/src/games/mo6tw/titlemenu.cpp index 5ca3b1292..52eaca2b3 100644 --- a/src/games/mo6tw/titlemenu.cpp +++ b/src/games/mo6tw/titlemenu.cpp @@ -44,19 +44,16 @@ TitleMenu::TitleMenu() { return SecondaryButtonOnClick(btn); }; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - // Initial Start menu button InitialStart = new TitleButton(0, MenuEntriesSprites[0], MenuEntriesHSprites[0], - nullSprite, glm::vec2(MenuEntriesX, MenuEntriesFirstY)); + glm::vec2(MenuEntriesX, MenuEntriesFirstY)); InitialStart->OnClickHandler = onClick; MainItems->Add(InitialStart, FDIR_DOWN); // Lockable Extra Story menu button ExtraStory = new TitleButton( - 1, MenuEntriesSprites[1], MenuEntriesHSprites[1], nullSprite, + 1, MenuEntriesSprites[1], MenuEntriesHSprites[1], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (1 * MenuEntriesYPadding))); ExtraStory->Enabled = false; ExtraStory->OnClickHandler = onClick; @@ -65,14 +62,14 @@ TitleMenu::TitleMenu() { // Continue menu button Continue = new TitleButton( - 2, MenuEntriesSprites[2], MenuEntriesHSprites[2], nullSprite, + 2, MenuEntriesSprites[2], MenuEntriesHSprites[2], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (2 * MenuEntriesYPadding))); Continue->OnClickHandler = onClick; MainItems->Add(Continue, FDIR_DOWN); // Lockable Memories menu button Memories = new TitleButton( - 3, MenuEntriesSprites[3], MenuEntriesHSprites[3], nullSprite, + 3, MenuEntriesSprites[3], MenuEntriesHSprites[3], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (3 * MenuEntriesYPadding))); Memories->Enabled = false; Memories->OnClickHandler = onClick; @@ -81,114 +78,114 @@ TitleMenu::TitleMenu() { // Encyclopedia menu button Encyclopedia = new TitleButton( - 4, MenuEntriesSprites[4], MenuEntriesHSprites[4], nullSprite, + 4, MenuEntriesSprites[4], MenuEntriesHSprites[4], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (4 * MenuEntriesYPadding))); Encyclopedia->OnClickHandler = onClick; MainItems->Add(Encyclopedia, FDIR_DOWN); // System menu button System = new TitleButton( - 5, MenuEntriesSprites[5], MenuEntriesHSprites[5], nullSprite, + 5, MenuEntriesSprites[5], MenuEntriesHSprites[5], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (5 * MenuEntriesYPadding))); System->OnClickHandler = onClick; MainItems->Add(System, FDIR_DOWN); // Exit menu button Exit = new TitleButton( - 6, MenuEntriesSprites[6], MenuEntriesHSprites[6], nullSprite, + 6, MenuEntriesSprites[6], MenuEntriesHSprites[6], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (6 * MenuEntriesYPadding))); Exit->OnClickHandler = onClick; MainItems->Add(Exit, FDIR_DOWN); // Load secondary Continue menu button Load = new TitleButton( - 0, MenuEntriesSprites[10], MenuEntriesHSprites[10], nullSprite, + 0, MenuEntriesSprites[10], MenuEntriesHSprites[10], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (3 * MenuEntriesYPadding))); Load->OnClickHandler = secondaryOnClick; ContinueItems->Add(Load, FDIR_DOWN); // Quick Load secondary Continue menu button - QuickLoad = new TitleButton( - 1, MenuEntriesSprites[11], MenuEntriesHSprites[11], nullSprite, - glm::vec2(MenuEntriesX - 20.0f, - MenuEntriesFirstY + (4 * MenuEntriesYPadding))); + QuickLoad = + new TitleButton(1, MenuEntriesSprites[11], MenuEntriesHSprites[11], + glm::vec2(MenuEntriesX - 20.0f, + MenuEntriesFirstY + (4 * MenuEntriesYPadding))); QuickLoad->OnClickHandler = secondaryOnClick; ContinueItems->Add(QuickLoad, FDIR_DOWN); // Prologue secondary Extra Story menu button Prologue = new TitleButton( - 0, MenuEntriesSprites[7], MenuEntriesHSprites[7], nullSprite, + 0, MenuEntriesSprites[7], MenuEntriesHSprites[7], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (2 * MenuEntriesYPadding))); Prologue->OnClickHandler = secondaryOnClick; ExtraStoryItems->Add(Prologue, FDIR_DOWN); // Otome Judge feat.Shin secondary Extra Story menu button - OtomeJudgeShin = new TitleButton( - 1, MenuEntriesSprites[8], MenuEntriesHSprites[8], nullSprite, - glm::vec2(MenuEntriesX - 20.0f, - MenuEntriesFirstY + (3 * MenuEntriesYPadding))); + OtomeJudgeShin = + new TitleButton(1, MenuEntriesSprites[8], MenuEntriesHSprites[8], + glm::vec2(MenuEntriesX - 20.0f, + MenuEntriesFirstY + (3 * MenuEntriesYPadding))); OtomeJudgeShin->OnClickHandler = secondaryOnClick; ExtraStoryItems->Add(OtomeJudgeShin, FDIR_DOWN); // Warning secondary Extra Story menu button - Warning = new TitleButton( - 2, MenuEntriesSprites[9], MenuEntriesHSprites[9], nullSprite, - glm::vec2(MenuEntriesX - 40.0f, - MenuEntriesFirstY + (4 * MenuEntriesYPadding))); + Warning = + new TitleButton(2, MenuEntriesSprites[9], MenuEntriesHSprites[9], + glm::vec2(MenuEntriesX - 40.0f, + MenuEntriesFirstY + (4 * MenuEntriesYPadding))); Warning->OnClickHandler = secondaryOnClick; ExtraStoryItems->Add(Warning, FDIR_DOWN); // Warning secondary Extra Story menu button ClearList = new TitleButton( - 0, MenuEntriesSprites[13], MenuEntriesHSprites[13], nullSprite, + 0, MenuEntriesSprites[13], MenuEntriesHSprites[13], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (4 * MenuEntriesYPadding))); ClearList->OnClickHandler = secondaryOnClick; MemoriesItems->Add(ClearList, FDIR_DOWN); // Warning secondary Extra Story menu button - Album = new TitleButton( - 1, MenuEntriesSprites[14], MenuEntriesHSprites[14], nullSprite, - glm::vec2(MenuEntriesX - 20.0f, - MenuEntriesFirstY + (5 * MenuEntriesYPadding))); + Album = + new TitleButton(1, MenuEntriesSprites[14], MenuEntriesHSprites[14], + glm::vec2(MenuEntriesX - 20.0f, + MenuEntriesFirstY + (5 * MenuEntriesYPadding))); Album->OnClickHandler = secondaryOnClick; MemoriesItems->Add(Album, FDIR_DOWN); // Warning secondary Extra Story menu button - Music = new TitleButton( - 2, MenuEntriesSprites[15], MenuEntriesHSprites[15], nullSprite, - glm::vec2(MenuEntriesX - 40.0f, - MenuEntriesFirstY + (6 * MenuEntriesYPadding))); + Music = + new TitleButton(2, MenuEntriesSprites[15], MenuEntriesHSprites[15], + glm::vec2(MenuEntriesX - 40.0f, + MenuEntriesFirstY + (6 * MenuEntriesYPadding))); Music->OnClickHandler = secondaryOnClick; MemoriesItems->Add(Music, FDIR_DOWN); // Warning secondary Extra Story menu button - Movie = new TitleButton( - 3, MenuEntriesSprites[16], MenuEntriesHSprites[16], nullSprite, - glm::vec2(MenuEntriesX - 60.0f, - MenuEntriesFirstY + (7 * MenuEntriesYPadding))); + Movie = + new TitleButton(3, MenuEntriesSprites[16], MenuEntriesHSprites[16], + glm::vec2(MenuEntriesX - 60.0f, + MenuEntriesFirstY + (7 * MenuEntriesYPadding))); Movie->OnClickHandler = secondaryOnClick; MemoriesItems->Add(Movie, FDIR_DOWN); // Warning secondary Extra Story menu button - ActorsVoice = new TitleButton( - 4, MenuEntriesSprites[17], MenuEntriesHSprites[17], nullSprite, - glm::vec2(MenuEntriesX - 80.0f, - MenuEntriesFirstY + (8 * MenuEntriesYPadding))); + ActorsVoice = + new TitleButton(4, MenuEntriesSprites[17], MenuEntriesHSprites[17], + glm::vec2(MenuEntriesX - 80.0f, + MenuEntriesFirstY + (8 * MenuEntriesYPadding))); ActorsVoice->OnClickHandler = secondaryOnClick; MemoriesItems->Add(ActorsVoice, FDIR_DOWN); // Option secondary System menu button Option = new TitleButton( - 0, MenuEntriesSprites[18], MenuEntriesHSprites[18], nullSprite, + 0, MenuEntriesSprites[18], MenuEntriesHSprites[18], glm::vec2(MenuEntriesX, MenuEntriesFirstY + (6 * MenuEntriesYPadding))); Option->OnClickHandler = secondaryOnClick; SystemItems->Add(Option, FDIR_DOWN); // System Save secondary System menu button - SystemSave = new TitleButton( - 1, MenuEntriesSprites[20], MenuEntriesHSprites[20], nullSprite, - glm::vec2(MenuEntriesX - 20.0f, - MenuEntriesFirstY + (7 * MenuEntriesYPadding))); + SystemSave = + new TitleButton(1, MenuEntriesSprites[20], MenuEntriesHSprites[20], + glm::vec2(MenuEntriesX - 20.0f, + MenuEntriesFirstY + (7 * MenuEntriesYPadding))); SystemSave->OnClickHandler = secondaryOnClick; SystemItems->Add(SystemSave, FDIR_DOWN); } diff --git a/src/games/mo8/optionsmenu.cpp b/src/games/mo8/optionsmenu.cpp index 91ea9da85..966f6cd2e 100644 --- a/src/games/mo8/optionsmenu.cpp +++ b/src/games/mo8/optionsmenu.cpp @@ -71,13 +71,11 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { PageControls = new Group(this); PageControls->FocusLock = false; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); auto nextPage = new Button(0, NextButtonSprite, NextButtonHighlightedSprite, - nullSprite, NextButtonPosition); + std::nullopt, NextButtonPosition); nextPage->OnClickHandler = nextPageOnClick; auto previousPage = - new Button(0, BackButtonSprite, BackButtonHighlightedSprite, nullSprite, + new Button(0, BackButtonSprite, BackButtonHighlightedSprite, std::nullopt, BackButtonPosition); previousPage->OnClickHandler = previousPageOnClick; PageControls->Add(nextPage); @@ -101,7 +99,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { for (int i = 0; i < TextSpeedOptionsNum; i++) { auto toggle = new Toggle( i, &MessageSpeedValues[i], TextSpeedOptionsHSprites[i], - TextSpeedOptionsSprites[i], nullSprite, glm::vec2(0.0f), false); + TextSpeedOptionsSprites[i], std::nullopt, glm::vec2(0.0f), false); toggle->OnClickHandler = textSpeedOnClick; textSpeedOptions->AddOption(toggle); } @@ -118,7 +116,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { for (int i = 0; i < AutoModeOptionsNum; i++) { auto toggle = new Toggle( i, &AutoModeWaitTimeValues[i], AutoModeOptionsHSprites[i], - AutoModeOptionsSprites[i], nullSprite, glm::vec2(0.0f), false); + AutoModeOptionsSprites[i], std::nullopt, glm::vec2(0.0f), false); toggle->OnClickHandler = autoModeWaitTimeOnClick; autoModeOptions->AddOption(toggle); } @@ -132,7 +130,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { ButtonHighlight, currentPos, OptionGroupItemsOffset); for (int i = 0; i < SkipModeOptionsNum; i++) { auto toggle = new Toggle(i, &SkipModeValues[i], SkipModeOptionsHSprites[i], - SkipModeOptionsSprites[i], nullSprite, + SkipModeOptionsSprites[i], std::nullopt, glm::vec2(0.0f), false); toggle->OnClickHandler = skipModeOnClick; skipModeOptions->AddOption(toggle); @@ -153,7 +151,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { for (int i = 0; i < SoundModeOptionsNum; i++) { voiceSyncOptions->AddOption(new Toggle( i, &FalseValue, SoundModeOptionsHSprites[i], SoundModeOptionsSprites[i], - nullSprite, glm::vec2(0.0f), false)); + std::nullopt, glm::vec2(0.0f), false)); } soundPage1->Add(voiceSyncOptions, FDIR_DOWN); currentPos += ListPadding; @@ -165,7 +163,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { for (int i = 0; i < SoundModeOptionsNum; i++) { voiceSkipOptions->AddOption(new Toggle( i, &FalseValue, SoundModeOptionsHSprites[i], SoundModeOptionsSprites[i], - nullSprite, glm::vec2(0.0f), false)); + std::nullopt, glm::vec2(0.0f), false)); } soundPage1->Add(voiceSkipOptions, FDIR_DOWN); currentPos += ListPadding; @@ -177,7 +175,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { for (int i = 0; i < SoundModeOptionsNum; i++) { voiceHighlightOptions->AddOption(new Toggle( i, &FalseValue, SoundModeOptionsHSprites[i], SoundModeOptionsSprites[i], - nullSprite, glm::vec2(0.0f), false)); + std::nullopt, glm::vec2(0.0f), false)); } soundPage1->Add(voiceHighlightOptions, FDIR_DOWN); Pages.push_back(std::move(soundPage1)); @@ -190,11 +188,11 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { // BGM volume options auto bgmVolumeOptions = - new OptionGroup(this, BgmVolumeLabel, BgmVolumeLabelH, nullSprite, + new OptionGroup(this, BgmVolumeLabel, BgmVolumeLabelH, std::nullopt, currentPos, OptionGroupSliderOffset); auto bgmVolumeSlider = new Scrollbar( 0, glm::vec2(0.0f), 0.0f, 1.0f, &Audio::GroupVolumes[Audio::ACG_BGM], - SBDIR_HORIZONTAL, SliderTrackSprite, nullSprite, SliderFillSprite); + SBDIR_HORIZONTAL, SliderTrackSprite, Sprite(), SliderFillSprite); bgmVolumeOptions->AddOption(bgmVolumeSlider); bgmVolumeSlider->FillBeforeTrack = true; soundPage2->Add(bgmVolumeOptions, FDIR_DOWN); @@ -202,11 +200,11 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { // Voice volume options auto voiceVolumeOptions = - new OptionGroup(this, VoiceVolumeLabel, VoiceVolumeLabelH, nullSprite, + new OptionGroup(this, VoiceVolumeLabel, VoiceVolumeLabelH, std::nullopt, currentPos, OptionGroupSliderOffset); auto voiceVolumeSlider = new Scrollbar( 0, glm::vec2(0.0f), 0.0f, 1.0f, &Audio::GroupVolumes[Audio::ACG_Voice], - SBDIR_HORIZONTAL, SliderTrackSprite, nullSprite, SliderFillSprite); + SBDIR_HORIZONTAL, SliderTrackSprite, std::nullopt, SliderFillSprite); voiceVolumeOptions->AddOption(voiceVolumeSlider); voiceVolumeSlider->FillBeforeTrack = true; soundPage2->Add(voiceVolumeOptions, FDIR_DOWN); @@ -214,11 +212,11 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { // SE volume options auto seVolumeOptions = - new OptionGroup(this, SeVolumeLabel, SeVolumeLabelH, nullSprite, + new OptionGroup(this, SeVolumeLabel, SeVolumeLabelH, std::nullopt, currentPos, OptionGroupSliderOffset); auto seVolumeSlider = new Scrollbar( 0, glm::vec2(0.0f), 0.0f, 1.0f, &Audio::GroupVolumes[Audio::ACG_SE], - SBDIR_HORIZONTAL, SliderTrackSprite, nullSprite, SliderFillSprite); + SBDIR_HORIZONTAL, SliderTrackSprite, std::nullopt, SliderFillSprite); seVolumeOptions->AddOption(seVolumeSlider); seVolumeSlider->FillBeforeTrack = true; soundPage2->Add(seVolumeOptions, FDIR_DOWN); @@ -227,17 +225,17 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { // SYSSE volume options auto systemSeVolumeOptions = new OptionGroup(this, SystemSeVolumeLabel, SystemSeVolumeLabelH, - nullSprite, currentPos, OptionGroupSliderOffset); + std::nullopt, currentPos, OptionGroupSliderOffset); auto systemSeVolumeSlider = new Scrollbar( 0, glm::vec2(0.0f), 0.0f, 1.0f, &Audio::GroupVolumes[Audio::ACG_SE], - SBDIR_HORIZONTAL, SliderTrackSprite, nullSprite, SliderFillSprite); + SBDIR_HORIZONTAL, SliderTrackSprite, std::nullopt, SliderFillSprite); systemSeVolumeOptions->AddOption(systemSeVolumeSlider); systemSeVolumeSlider->FillBeforeTrack = true; soundPage2->Add(systemSeVolumeOptions, FDIR_DOWN); currentPos += ListPadding; auto characterVoiceButton = new Button(0, CharacterVoiceVolumeLabel, CharacterVoiceVolumeLabelH, - nullSprite, currentPos); + std::nullopt, currentPos); soundPage2->Add(characterVoiceButton, FDIR_DOWN); Pages.push_back(std::move(soundPage2)); currentPos = ListStartingPosition; @@ -254,7 +252,7 @@ OptionsMenu::OptionsMenu() : UI::OptionsMenu() { for (int i = 0; i < QuickSaveOptionsNum; i++) { quickSaveOptions->AddOption(new Toggle( i, &FalseValue, QuickSaveOptionsHSprites[i], QuickSaveOptionsSprites[i], - nullSprite, glm::vec2(0.0f), false)); + std::nullopt, glm::vec2(0.0f), false)); } otherPage->Add(quickSaveOptions, FDIR_DOWN); Pages.push_back(std::move(otherPage)); diff --git a/src/games/mo8/savemenu.cpp b/src/games/mo8/savemenu.cpp index 4de1dc857..9ed2fd12e 100644 --- a/src/games/mo8/savemenu.cpp +++ b/src/games/mo8/savemenu.cpp @@ -41,12 +41,10 @@ SaveMenu::SaveMenu() : UI::SaveMenu() { PageControls = new Group(this); PageControls->FocusLock = false; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); auto nextPage = new Button(0, NextButtonSprite, NextButtonHighlightedSprite, - nullSprite, NextButtonPosition); + std::nullopt, NextButtonPosition); auto previousPage = - new Button(0, BackButtonSprite, BackButtonHighlightedSprite, nullSprite, + new Button(0, BackButtonSprite, BackButtonHighlightedSprite, std::nullopt, BackButtonPosition); PageControls->Add(nextPage); PageControls->Add(previousPage); diff --git a/src/games/mo8/systemmenu.cpp b/src/games/mo8/systemmenu.cpp index 107aa04ff..26dcf4a5d 100644 --- a/src/games/mo8/systemmenu.cpp +++ b/src/games/mo8/systemmenu.cpp @@ -36,14 +36,11 @@ SystemMenu::SystemMenu() { auto onClick = [this](auto* btn) { return MenuButtonOnClick(btn); }; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - for (int i = 0; i < MenuEntriesNum; i++) { - Button* menuButton = - new Button(i, MenuEntriesSprites[i], MenuEntriesHSprites[i], nullSprite, - glm::vec2(*MenuEntriesX, - *MenuEntriesFirstY + (*MenuEntriesYPadding * i))); + Button* menuButton = new Button( + i, MenuEntriesSprites[i], MenuEntriesHSprites[i], std::nullopt, + glm::vec2(*MenuEntriesX, + *MenuEntriesFirstY + (*MenuEntriesYPadding * i))); menuButton->LockedSprite = MenuEntriesLSprites[i]; menuButton->OnClickHandler = onClick; diff --git a/src/games/mo8/titlemenu.cpp b/src/games/mo8/titlemenu.cpp index 5e000743e..5990ef974 100644 --- a/src/games/mo8/titlemenu.cpp +++ b/src/games/mo8/titlemenu.cpp @@ -58,9 +58,6 @@ TitleMenu::TitleMenu() { }; auto galleryOnClick = [this](auto* btn) { return GalleryButtonOnClick(btn); }; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - // New Game menu button NewGame = new Button(0, MenuEntriesSprites[NewGameSpriteIndex], MenuEntriesHSprites[NewGameSpriteIndex], diff --git a/src/games/rne/sysmesbox.cpp b/src/games/rne/sysmesbox.cpp index 433a90b5e..ef0023f30 100644 --- a/src/games/rne/sysmesbox.cpp +++ b/src/games/rne/sysmesbox.cpp @@ -29,9 +29,6 @@ void SysMesBox::Show() { MessageItems = std::make_unique(this); ChoiceItems = std::make_unique(this); - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - auto onClick = [this](auto* btn) { return ChoiceItemOnClick(btn); }; float textBeginY = TextMiddleY - (TextMarginY * (4 + MessageCount)); @@ -44,17 +41,17 @@ void SysMesBox::Show() { } if (ChoiceCount == 1) { - WidgetOK = new Button(0, ButtonOK, ButtonOKHighlighted, nullSprite, + WidgetOK = new Button(0, ButtonOK, ButtonOKHighlighted, std::nullopt, glm::vec2(ButtonRightX, 0.0f)); WidgetOK->OnClickHandler = onClick; ChoiceItems->Add(WidgetOK, FDIR_RIGHT); } else if (ChoiceCount == 2) { - WidgetYes = new Button(0, ButtonYes, ButtonYesHighlighted, nullSprite, + WidgetYes = new Button(0, ButtonYes, ButtonYesHighlighted, std::nullopt, glm::vec2(ButtonYesX, 0.0f)); WidgetYes->OnClickHandler = onClick; ChoiceItems->Add(WidgetYes, FDIR_RIGHT); - WidgetNo = new Button(1, ButtonNo, ButtonNoHighlighted, nullSprite, + WidgetNo = new Button(1, ButtonNo, ButtonNoHighlighted, std::nullopt, glm::vec2(ButtonRightX, 0.0f)); WidgetNo->OnClickHandler = onClick; ChoiceItems->Add(WidgetNo, FDIR_LEFT); @@ -157,12 +154,13 @@ void SysMesBox::Update(float dt) { float buttonYesSpriteWidth = ButtonYWidthBase + labelButtonSpriteOffsetX; if (buttonYesSpriteWidth > ButtonWidth) buttonYesSpriteWidth = ButtonWidth; - WidgetYes->NormalSprite.Bounds = RectF( - WidgetYes->NormalSprite.Bounds.X, WidgetYes->NormalSprite.Bounds.Y, - buttonYesSpriteWidth, WidgetYes->NormalSprite.Bounds.Height); - WidgetYes->FocusedSprite.Bounds = RectF( - WidgetYes->FocusedSprite.Bounds.X, WidgetYes->FocusedSprite.Bounds.Y, - buttonYesSpriteWidth, WidgetYes->FocusedSprite.Bounds.Height); + WidgetYes->NormalSprite->Bounds = RectF( + WidgetYes->NormalSprite->Bounds.X, WidgetYes->NormalSprite->Bounds.Y, + buttonYesSpriteWidth, WidgetYes->NormalSprite->Bounds.Height); + WidgetYes->FocusedSprite->Bounds = + RectF(WidgetYes->FocusedSprite->Bounds.X, + WidgetYes->FocusedSprite->Bounds.Y, buttonYesSpriteWidth, + WidgetYes->FocusedSprite->Bounds.Height); ButtonYesX = ButtonYesDisplayXBase - labelButtonSpriteOffsetX; WidgetYes->MoveTo(glm::vec2(ButtonYesX, BoxBottomY - ButtonYOffset)); } @@ -173,21 +171,23 @@ void SysMesBox::Update(float dt) { if (buttonRightSpriteWidth > ButtonWidth) buttonRightSpriteWidth = ButtonWidth; if (WidgetNo) { - WidgetNo->NormalSprite.Bounds = RectF( - WidgetNo->NormalSprite.Bounds.X, WidgetNo->NormalSprite.Bounds.Y, - buttonRightSpriteWidth, WidgetNo->NormalSprite.Bounds.Height); - WidgetNo->FocusedSprite.Bounds = RectF( - WidgetNo->FocusedSprite.Bounds.X, WidgetNo->FocusedSprite.Bounds.Y, - buttonRightSpriteWidth, WidgetNo->FocusedSprite.Bounds.Height); + WidgetNo->NormalSprite->Bounds = RectF( + WidgetNo->NormalSprite->Bounds.X, WidgetNo->NormalSprite->Bounds.Y, + buttonRightSpriteWidth, WidgetNo->NormalSprite->Bounds.Height); + WidgetNo->FocusedSprite->Bounds = + RectF(WidgetNo->FocusedSprite->Bounds.X, + WidgetNo->FocusedSprite->Bounds.Y, buttonRightSpriteWidth, + WidgetNo->FocusedSprite->Bounds.Height); WidgetNo->MoveTo(glm::vec2(ButtonRightX, BoxBottomY - ButtonYOffset)); } if (WidgetOK) { - WidgetOK->NormalSprite.Bounds = RectF( - WidgetOK->NormalSprite.Bounds.X, WidgetOK->NormalSprite.Bounds.Y, - buttonRightSpriteWidth, WidgetOK->NormalSprite.Bounds.Height); - WidgetOK->FocusedSprite.Bounds = RectF( - WidgetOK->FocusedSprite.Bounds.X, WidgetOK->FocusedSprite.Bounds.Y, - buttonRightSpriteWidth, WidgetOK->FocusedSprite.Bounds.Height); + WidgetOK->NormalSprite->Bounds = RectF( + WidgetOK->NormalSprite->Bounds.X, WidgetOK->NormalSprite->Bounds.Y, + buttonRightSpriteWidth, WidgetOK->NormalSprite->Bounds.Height); + WidgetOK->FocusedSprite->Bounds = + RectF(WidgetOK->FocusedSprite->Bounds.X, + WidgetOK->FocusedSprite->Bounds.Y, buttonRightSpriteWidth, + WidgetOK->FocusedSprite->Bounds.Height); WidgetOK->MoveTo(glm::vec2(ButtonRightX, BoxBottomY - ButtonYOffset)); } } diff --git a/src/games/rne/systemmenu.cpp b/src/games/rne/systemmenu.cpp index 471ae5f41..5b602a911 100644 --- a/src/games/rne/systemmenu.cpp +++ b/src/games/rne/systemmenu.cpp @@ -32,12 +32,9 @@ SystemMenu::SystemMenu() { auto onClick = [this](auto* btn) { return MenuButtonOnClick(btn); }; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - for (int i = 0; i < MenuEntriesNum; i++) { SysMenuButton* menuButton = new SysMenuButton( - i, MenuEntriesSprites[i], nullSprite, MenuEntriesHSprites[i], + i, MenuEntriesSprites[i], MenuEntriesHSprites[i], glm::vec2(*MenuEntriesX, *MenuEntriesFirstY + (*MenuEntriesYPadding * i))); @@ -139,7 +136,7 @@ void SystemMenu::Update(float dt) { item->Tint.a = glm::smoothstep( 0.0f, 1.0f, 1.0f - (idx + 1) * (1.0f - EntriesMoveAnimation.Progress)); Button* button = (Button*)item; - button->HighlightSprite.Bounds.Width = + button->HighlightSprite->Bounds.Width = MenuEntriesTargetWidth * HighlightAnimation.Progress; idx++; } diff --git a/src/hud/dialoguebox.cpp b/src/hud/dialoguebox.cpp index b99ee1416..fb9014888 100644 --- a/src/hud/dialoguebox.cpp +++ b/src/hud/dialoguebox.cpp @@ -55,28 +55,28 @@ PlainDialogueBox::PlainDialogueBox(const DialoguePage& page) : DialogueBox(page) { using namespace UI::Widgets; - Sprite nullSprite = Sprite(); - nullSprite.Bounds = RectF(0.0f, 0.0f, 0.0f, 0.0f); - if (HasAutoButton) { - ControlButtons.emplace_back(std::make_unique