Marvel's Spider-Man 2
Characters stay in a T-pose and the symbiote breaks on M1-M4 Macs: D3DMetal reads and writes typed buffers only to element 2^28.
What you see
Characters stay in a T-pose; the symbiote shows up as spikes, a flat black sheet, or not at all; brief black blocks flash in the opening sandstorm stage
Why it happens
On M1-M4 Macs, D3DMetal returns 0 for typed buffer reads past element 2^28 and drops typed writes past it. The black blocks come from a missing barrier after the volumetric fog copy
What the fix changes
macprotips': the wide R32 views made raw, and four shaders rebuilt raw from your own exe. Ours: no DLL override, and a UAV barrier after CS_VolumetricFogCopy
The code
macprotips': the wide R32 views past element 2^28 are created raw, which D3DMetal reads in full.
fixes/sm2-tpose-fix.c · hk_CreateShaderResourceView, lines 565–587static void STDMETHODCALLTYPE hk_CreateShaderResourceView(ID3D12Device *device, ID3D12Resource *resource,
const D3D12_SHADER_RESOURCE_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE handle)
{
void (STDMETHODCALLTYPE *orig)(ID3D12Device *, ID3D12Resource *, const D3D12_SHADER_RESOURCE_VIEW_DESC *,
D3D12_CPU_DESCRIPTOR_HANDLE) = orig_fn(device, DEV_IDX(CreateShaderResourceView));
if (desc && desc->ViewDimension == D3D12_SRV_DIMENSION_BUFFER && desc->Buffer.NumElements > WIDE_VIEW
&& !(desc->Buffer.Flags & D3D12_BUFFER_SRV_FLAG_RAW)
&& (desc->Format == DXGI_FORMAT_R32_UINT || desc->Format == DXGI_FORMAT_R32_SINT
|| desc->Format == DXGI_FORMAT_R32_FLOAT))
{
D3D12_SHADER_RESOURCE_VIEW_DESC raw = *desc;
raw.Format = DXGI_FORMAT_R32_TYPELESS;
raw.Buffer.Flags |= D3D12_BUFFER_SRV_FLAG_RAW;
raw.Buffer.StructureByteStride = 0;
if (InterlockedIncrement(&g_views) <= 4)
log_msg("Wide typed view (%u elements) created as a raw view", desc->Buffer.NumElements);
orig(device, resource, &raw, handle);
return;
}
orig(device, resource, desc, handle);
}Ours: a UAV barrier after the volumetric fog copy, which removed the black blocks in the sandstorm stage.
fixes/sm2-tpose-fix.c · hk_Dispatch, lines 411–426static void STDMETHODCALLTYPE hk_Dispatch(ID3D12GraphicsCommandList *list, UINT x, UINT y, UINT z)
{
void (STDMETHODCALLTYPE *orig)(ID3D12GraphicsCommandList *, UINT, UINT, UINT) = orig_fn(list, LIST_IDX(Dispatch));
orig(list, x, y, z);
if (t_bound.list == list && t_bound.fog)
{
D3D12_RESOURCE_BARRIER barrier;
memset(&barrier, 0, sizeof(barrier));
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
barrier.UAV.pResource = NULL; /* every UAV access before, against every one after */
list->lpVtbl->ResourceBarrier(list, 1, &barrier);
InterlockedIncrement(&g_fog_barriers);
}
}Thanks to
- macprotipsThe diagnosis, the raw views and the four rewritten shaders (public domain). MacGameFix adds a carrier that needs no DLL override and a barrier after the volumetric fog copy.
Details
- Needs
- D3DMetal, D3D12
- Installer
- install-sm2-fix.sh
- Executable
- Spider-Man2.exe
- Built from
- sm2-tpose-fix.c, sm2fix_core.c, sm2-shadertool.c, sm2-shaderfix.c
- Verified on
- Preview 27, through NotProton; M5 Macs do not have the limit