Compare commits

...

2 Commits

Author SHA1 Message Date
Dusk-92 eb083a0005 test: build DIP passthrough isolation 2026-08-29 18:58:31 +02:00
Dusk-92 b97c74469c test: hook DIP as pure passthrough 2026-08-29 18:58:21 +02:00
2 changed files with 60 additions and 73 deletions
@@ -0,0 +1,55 @@
name: V37A DIP Passthrough
on:
push:
branches:
- test/v37a-dip-passthrough
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: '0.16.0'
- name: Build
shell: bash
run: |
set -euo pipefail
zig build all-variants -Doptimize=ReleaseSmall \
-Dweirdperformance=false \
-Doutline=true \
-Dcustomassets=true \
-Dtransmogfix=true
- name: Package
shell: bash
run: |
set -euo pipefail
rm -rf package dist
mkdir -p package/DLL package/Interface/AddOns/WeirdUtils_Outline dist
cp zig-out/variants/outline.dll package/DLL/outline.dll
cp src/outline/addon/Bindings.xml package/Interface/AddOns/WeirdUtils_Outline/
cp src/outline/addon/Outline.lua package/Interface/AddOns/WeirdUtils_Outline/
cp src/outline/addon/WeirdUtils_Outline.toc package/Interface/AddOns/WeirdUtils_Outline/
printf '%s\n' \
'V37A DIP passthrough isolation test.' \
'EndScene and DrawIndexedPrimitive vtable hooks are installed.' \
'DIP detour performs no Outline capture/state/resource work and immediately calls original DIP.' \
'Reset remains untouched.' \
'Visible outline is intentionally absent in this diagnostic build.' \
'main branch untouched; WeirdPerformance not modified.' \
> package/README_TEST.txt
(cd package && sha256sum DLL/outline.dll > SHA256SUMS.txt && zip -r ../dist/WeirdUtils_V37A_DIP_PASSTHROUGH.zip DLL Interface README_TEST.txt SHA256SUMS.txt)
- uses: actions/upload-artifact@v4
with:
name: WeirdUtils-V37A-DIP-PASSTHROUGH
path: dist/WeirdUtils_V37A_DIP_PASSTHROUGH.zip
if-no-files-found: error
+5 -73
View File
@@ -996,79 +996,10 @@ fn hkDIP(
) callconv(hook.cc.stdcall) i32 {
debug_dip_seen = true;
// Isolation test: keep the DIP vtable detour installed, but do no
// Outline state capture/resource work here. Call the original directly.
const OrigDIP = *const fn (*anyopaque, u32, i32, u32, u32, u32, u32) callconv(hook.cc.stdcall) i32;
const origFn: OrigDIP = @ptrFromInt(orig_dip);
// ---- Cache outline draws for EndScene replay ----
if (model_hook.rendering_outline) {
debug_outline_dip_seen = true;
const model_ptr = model_hook.current_model;
const color = tracker.getModelColor(model_ptr) orelse
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
const category = tracker.getModelCategory(model_ptr);
// Ensure resources will be available for replay in EndScene
if (!shaders_attempted) ensureShaders(device);
ensureResources(device);
if (outline_ps == null or rt_silhouette_surf == null)
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
// Cache if room available
if (cached_draw_count < MAX_CACHED_DRAWS) {
const idx = cached_draw_count;
var draw = &cached_draws[idx];
// Draw parameters
draw.prim_type = prim_type;
draw.base_vtx = base_vtx;
draw.min_vtx = min_vtx;
draw.num_verts = num_verts;
draw.start_idx = start_idx;
draw.prim_count = prim_count;
// Outline info
draw.color = color;
draw.category = category;
// Capture current GPU state (AddRef COM objects to keep them alive)
deviceGetStreamSource(device, 0, &draw.vb, &draw.vb_offset, &draw.vb_stride);
// GetStreamSource AddRef's the VB - we keep the ref until replay
draw.ib = deviceGetIndices(device);
// GetIndices AddRef's the IB
draw.vertex_decl = deviceGetPtr(device, types.VT.GetVertexDeclaration);
// GetVertexDeclaration AddRef's
draw.vertex_shader = deviceGetPtr(device, types.VT.GetVertexShader);
// GetVertexShader AddRef's
for (0..4) |stage| {
draw.tex[stage] = deviceGetTexture(device, @intCast(stage));
draw.alpha_op[stage] = deviceGetTSS(device, @intCast(stage), types.D3DTSS.ALPHAOP);
draw.alpha_arg1[stage] = deviceGetTSS(device, @intCast(stage), types.D3DTSS.ALPHAARG1);
draw.alpha_arg2[stage] = deviceGetTSS(device, @intCast(stage), types.D3DTSS.ALPHAARG2);
}
draw.pixel_shader = deviceGetPtr(device, types.VT.GetPixelShader);
draw.state_block = deviceCreateStateBlock(device);
if (draw.state_block != null) debug_state_block_seen = true;
draw.alpha_test_enable = deviceGetRS(device, types.D3DRS.ALPHATESTENABLE);
draw.alpha_ref = deviceGetRS(device, types.D3DRS.ALPHAREF);
draw.alpha_func = deviceGetRS(device, types.D3DRS.ALPHAFUNC);
draw.alpha_blend_enable = deviceGetRS(device, types.D3DRS.ALPHABLENDENABLE);
draw.src_blend = deviceGetRS(device, types.D3DRS.SRCBLEND);
draw.dst_blend = deviceGetRS(device, types.D3DRS.DESTBLEND);
// Capture VS constants (bone matrices, world/view/proj transforms)
deviceGetVSConstF(device, 0, &draw.vs_consts, MAX_VS_CONST_REGS);
cached_draw_count = idx + 1;
frame_has_outlines = true;
debug_cached_draw_seen = true;
}
// DEBUG23: no stencil writes. Preserve WoW's D3D state and draw once.
// The cached geometry is replayed later into the silhouette RT.
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
}
// ---- Normal path ----
return origFn(device, prim_type, base_vtx, min_vtx, num_verts, start_idx, prim_count);
}
@@ -1627,9 +1558,10 @@ pub fn installHooks() bool {
const vtable_ptr = getD3D9VTable() orelse return false;
d3d9_vtable = vtable_ptr;
// Isolation test: hook EndScene only.
// DrawIndexedPrimitive and Reset remain untouched.
// Isolation test: hook EndScene + DrawIndexedPrimitive.
// Reset remains untouched.
if (!patchVtableEntry(vtable_ptr, types.VT.EndScene, @intFromPtr(&hkEndScene), &orig_endscene)) return false;
if (!patchVtableEntry(vtable_ptr, types.VT.DrawIndexedPrimitive, @intFromPtr(&hkDIP), &orig_dip)) return false;
hooks_installed = true;
return true;