mirror of
https://github.com/sven-n/MuMain
synced 2026-08-15 20:32:27 -04:00
Two changes bundled together: moving skeletal skinning off the CPU onto the
GPU, and retiring the fixed-function pipeline (FFP) in favor of a real
backend-agnostic render hardware interface (RHI) with a GL implementation.
GPU bone skinning
- Per-vertex skeletal skinning (BMD::Transform()'s CPU loop, previously run
for every vertex of every visible body, every frame) moves to the GPU:
the CPU now only computes and uploads the (much smaller) per-bone matrix
palette; the vertex shader does the per-vertex transform in parallel.
- Measured result: `Transform()` self-time at a standard crowded spot
dropped from ~0.25ms to 0.01-0.02ms -- a 15-20x reduction. This is exactly
the cost that scales worst in an MMO client (town crowds, mass PK/boss
events), so the win is disproportionately larger in the scenarios that
used to hurt most.
- Cloth cape meshes are the one remaining CPU-skinned case (pinned-vertex
physics read/write-back), deliberately deferred rather than forced into
this pass.
Eliminating the fixed-function pipeline
- Render/Core/ImmediateRenderer.{h,cpp} ("IR"): a streaming-VBO bridge that
mirrors the legacy glBegin/glEnd/glVertex/glColor/glTexCoord immediate-mode
API 1:1 (decomposing GL_QUADS to GL_TRIANGLES), so the ~hundreds of legacy
immediate-mode call sites across UI/effects code didn't need a per-site
rewrite -- they draw through IR, which streams into a VBO and issues a real
shader-backed glDrawArrays instead of relying on FFP's glBegin/glEnd.
- Render/Core/GlobalUBO.{h,cpp} / SceneUBO.{h,cpp} / BoneUBO.{h,cpp}: replace
the FFP matrix stack (glMatrixMode/glLoadMatrix/glMultMatrix) and per-bone
transform state with explicit uniform buffers the shaders read instead.
- Render/Core/GLColorIntercept.h: glColor*() under Core Profile is a no-op
and glGetFloatv(GL_CURRENT_COLOR, ...) is illegal, so ~340 RenderColor()/
RenderBitmap()-family call sites that used to read back "current color"
via that query now read a shadow g_CurrentColor mirrored by macro-
intercepted glColor* wrappers instead.
- Render/Core/BindState.{h,cpp}: single-source-of-truth glUseProgram/
glBindTexture/glBindVertexArray wrapper with last-bound-id caching, so
shader/texture/VAO state is tracked explicitly instead of relying on GL's
implicit FFP-era binding state.
- tools/check_gl_wrapper_monopoly.py, wired into CMake as an always-rerun
build target (CheckGLWrapperMonopoly): fails the build if a raw gl*() call
appears outside Render/ that isn't on its allowlist, so no new FFP call
site can sneak back in. The current allowlist is a deliberately documented
set of deferrals (screenshot readback, one-time startup queries, event fog
params), not oversights.
- ~60 supporting files (Models/Effects/UI/GameMaps/Terrain/etc.) updated to
route through the new wrapper family instead of calling gl* directly.
RHI abstraction
- Render/RHI/{RHI,RHI_GL}.{h,cpp}: buffer/texture/uniform-block/draw
abstraction so rendering code targets a stable interface rather than raw
GL calls -- a GL implementation today, sized to add other backends later
without touching call sites.
- Render/Shaders/{BMDMeshShader,TerrainShader,PassthroughShader,
PlanarShadowShader,ItemSpecularShader}.{h,cpp} (+ glsl/*.vert/.frag):
GLSL shader pairs replacing the fixed-function mesh/terrain/UI-sprite/
planar-shadow/item-specular rendering paths -- this is also what the GPU
skinning above actually runs inside of.
80 lines
9.3 KiB
XML
80 lines
9.3 KiB
XML
<Project Sdk="Microsoft.NET.Sdk">
|
|
|
|
<PropertyGroup>
|
|
<TargetFramework>net10.0</TargetFramework>
|
|
<!-- Platform and PlatformTarget are set by CMake via command line -->
|
|
<Nullable>enable</Nullable>
|
|
<SupportNativeAot>true</SupportNativeAot>
|
|
<IsAotCompatible>true</IsAotCompatible>
|
|
<PublishAot>true</PublishAot>
|
|
<OptimizationPreference>Speed</OptimizationPreference>
|
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
|
|
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
|
<WarningsAsErrors>nullable;CS4014;VSTHRD110;VSTHRD100</WarningsAsErrors>
|
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.20">
|
|
<PrivateAssets>all</PrivateAssets>
|
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
</PackageReference>
|
|
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
|
|
<PrivateAssets>all</PrivateAssets>
|
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
|
</PackageReference>
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="MUnique.OpenMU.Network.Packets" Version="0.9.9" />
|
|
<PackageReference Include="Pipelines.Sockets.Unofficial" Version="2.2.8" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<AdditionalFiles Include="..\stylecop.json" Link="stylecop.json" />
|
|
<None Include="..\.editorconfig" Link=".editorconfig" />
|
|
</ItemGroup>
|
|
|
|
|
|
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(ci)'!='true'"
|
|
Inputs="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ClientToServer\ClientToServerPackets.xml;
|
|
$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ChatServer\ChatServerPackets.xml;
|
|
$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ConnectServer\ConnectServerPackets.xml;
|
|
$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\CommonEnums.xml;
|
|
GenerateExtensionsDotNet.xslt;GenerateEnums.xslt;GenerateFunctionsHeader.xslt;GenerateFunctions.xslt;GenerateBindingsHeader.xslt"
|
|
Outputs="ConnectionManager.ClientToServerFunctions.cs;ConnectionManager.ChatServerFunctions.cs;ConnectionManager.ConnectServerFunctions.cs;
|
|
..\src\source\Dotnet\PacketFunctions_CommonEnums.h;..\src\source\Dotnet\PacketFunctions_ClientToServer_Enums.h;..\src\source\Dotnet\PacketFunctions_ChatServer_Enums.h;..\src\source\Dotnet\PacketFunctions_ConnectServer_Enums.h;
|
|
..\src\source\Dotnet\PacketFunctions_ClientToServer.h;..\src\source\Dotnet\PacketFunctions_ChatServer.h;..\src\source\Dotnet\PacketFunctions_ConnectServer.h;
|
|
..\src\source\Dotnet\PacketFunctions_ClientToServer.cpp;..\src\source\Dotnet\PacketFunctions_ChatServer.cpp;..\src\source\Dotnet\PacketFunctions_ConnectServer.cpp;
|
|
..\src\source\Dotnet\PacketBindings_ClientToServer.h;..\src\source\Dotnet\PacketBindings_ChatServer.h;..\src\source\Dotnet\PacketBindings_ConnectServer.h">
|
|
<!-- We only run the transformation locally on our dev environment with visual studio.
|
|
The CI environment is identified by the parameter 'ci'. It's set in the azure pipelines and Dockerfile.
|
|
If you run into errors here under Linux/Mac OS, it might help to add this parameter, too.
|
|
Inputs/Outputs added 2026-08-03: without them this target has no incremental-build tracking
|
|
and MSBuild reruns it (unconditionally overwriting every output below) on every single
|
|
dotnet build/publish, even when the packet XML/XSLT sources haven't changed. See
|
|
CLIENT/src/CMakeLists.txt's DOTNET_DLL_PATH comment for the CMake-side half of this fix. -->
|
|
<XslTransformation OutputPaths="ConnectionManager.ClientToServerFunctions.cs" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ClientToServer\ClientToServerPackets.xml" XslInputPath="GenerateExtensionsDotNet.xslt" Parameters="<Parameter Name='subNamespace' Value='ClientToServer'/>" />
|
|
<XslTransformation OutputPaths="ConnectionManager.ChatServerFunctions.cs" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ChatServer\ChatServerPackets.xml" XslInputPath="GenerateExtensionsDotNet.xslt" Parameters="<Parameter Name='subNamespace' Value='ChatServer'/>" />
|
|
<XslTransformation OutputPaths="ConnectionManager.ConnectServerFunctions.cs" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ConnectServer\ConnectServerPackets.xml" XslInputPath="GenerateExtensionsDotNet.xslt" Parameters="<Parameter Name='subNamespace' Value='ConnectServer'/>" />
|
|
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_CommonEnums.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\CommonEnums.xml" XslInputPath="GenerateEnums.xslt" Parameters="<Parameter Name='subNamespace' Value='CommonEnums'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ClientToServer_Enums.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ClientToServer\ClientToServerPackets.xml" XslInputPath="GenerateEnums.xslt" Parameters="<Parameter Name='subNamespace' Value='ClientToServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ChatServer_Enums.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ChatServer\ChatServerPackets.xml" XslInputPath="GenerateEnums.xslt" Parameters="<Parameter Name='subNamespace' Value='ChatServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ConnectServer_Enums.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ConnectServer\ConnectServerPackets.xml" XslInputPath="GenerateEnums.xslt" Parameters="<Parameter Name='subNamespace' Value='ConnectServer'/>" />
|
|
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ClientToServer.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ClientToServer\ClientToServerPackets.xml" XslInputPath="GenerateFunctionsHeader.xslt" Parameters="<Parameter Name='subNamespace' Value='ClientToServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ChatServer.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ChatServer\ChatServerPackets.xml" XslInputPath="GenerateFunctionsHeader.xslt" Parameters="<Parameter Name='subNamespace' Value='ChatServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ConnectServer.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ConnectServer\ConnectServerPackets.xml" XslInputPath="GenerateFunctionsHeader.xslt" Parameters="<Parameter Name='subNamespace' Value='ConnectServer'/>" />
|
|
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ClientToServer.cpp" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ClientToServer\ClientToServerPackets.xml" XslInputPath="GenerateFunctions.xslt" Parameters="<Parameter Name='subNamespace' Value='ClientToServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ChatServer.cpp" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ChatServer\ChatServerPackets.xml" XslInputPath="GenerateFunctions.xslt" Parameters="<Parameter Name='subNamespace' Value='ChatServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketFunctions_ConnectServer.cpp" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ConnectServer\ConnectServerPackets.xml" XslInputPath="GenerateFunctions.xslt" Parameters="<Parameter Name='subNamespace' Value='ConnectServer'/>" />
|
|
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketBindings_ClientToServer.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ClientToServer\ClientToServerPackets.xml" XslInputPath="GenerateBindingsHeader.xslt" Parameters="<Parameter Name='subNamespace' Value='ClientToServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketBindings_ChatServer.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ChatServer\ChatServerPackets.xml" XslInputPath="GenerateBindingsHeader.xslt" Parameters="<Parameter Name='subNamespace' Value='ChatServer'/>" />
|
|
<XslTransformation OutputPaths="..\src\source\Dotnet\PacketBindings_ConnectServer.h" XmlInputPaths="$(NuGetPackageRoot)\munique.openmu.network.packets\0.9.9\contentFiles\any\net10.0\ConnectServer\ConnectServerPackets.xml" XslInputPath="GenerateBindingsHeader.xslt" Parameters="<Parameter Name='subNamespace' Value='ConnectServer'/>" />
|
|
</Target>
|
|
</Project>
|