mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-26 04:39:17 +08:00
864cbb0fa0
* [Core] Add POSIX native execution and PS5 SELF support Extend the native backend, guest TLS, fixed-address memory, and loader paths needed by PS5 titles on Windows, Linux, and macOS. Keep workstation GC so high-core-count hosts do not reserve over fixed guest image bases. * [HLE] Expand PS5 service and media compatibility Add the kernel, threading, save-data, networking, audio, video-codec, font, dialog, and service exports required by newer PS5 software. Preserve every SysAbi NID currently registered by main while adding the compatibility surface used by ASTRO BOT. * [AGC/Vulkan] Extend Gen5 shader and presentation support Expand PM4 handling, Gen5 shader translation, MRT and packed export support, guest image tracking, depth initialization, texture aliasing, and Vulkan presentation. Add the performance overlay and address-filtered diagnostics used to validate ASTRO BOT with original shaders. * [Core] Align static TLS reservation across hosts * [Pad] Align primary user ID with UserService * [Gpu] Preserve runtime scalar buffers across renderer seam * [AGC] Restore omitted command helper exports * [Vulkan] Reuse primary views for promoted MRT targets * [Vulkan] Preserve scratch storage bindings in compute dispatches
155 lines
4.7 KiB
C#
155 lines
4.7 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using SharpEmu.HLE;
|
|
using System.Buffers.Binary;
|
|
|
|
namespace SharpEmu.ShaderCompiler;
|
|
|
|
public static class Gen5ShaderMetadataReader
|
|
{
|
|
private const ulong ShaderUserDataOffset = 0x08;
|
|
private const int ResourceClassCount = 4;
|
|
private const int MaxMetadataEntries = 4096;
|
|
|
|
public static bool TryRead(
|
|
CpuContext ctx,
|
|
ulong shaderHeaderAddress,
|
|
out Gen5ShaderMetadata metadata)
|
|
{
|
|
metadata = default!;
|
|
if (!TryReadUInt64(ctx, shaderHeaderAddress + ShaderUserDataOffset, out var userDataAddress) ||
|
|
userDataAddress == 0 ||
|
|
!TryReadUInt64(ctx, userDataAddress, out var directResourceOffsetsAddress))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var resourceOffsets = new ulong[ResourceClassCount];
|
|
for (var resourceClass = 0; resourceClass < ResourceClassCount; resourceClass++)
|
|
{
|
|
if (!TryReadUInt64(
|
|
ctx,
|
|
userDataAddress + 0x08 + (ulong)(resourceClass * sizeof(ulong)),
|
|
out resourceOffsets[resourceClass]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!TryReadUInt16(ctx, userDataAddress + 0x28, out var extendedUserDataSize) ||
|
|
!TryReadUInt16(ctx, userDataAddress + 0x2A, out var shaderResourceTableSize) ||
|
|
!TryReadUInt16(ctx, userDataAddress + 0x2C, out var directResourceCount) ||
|
|
directResourceCount > MaxMetadataEntries)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var resourceCounts = new ushort[ResourceClassCount];
|
|
for (var resourceClass = 0; resourceClass < ResourceClassCount; resourceClass++)
|
|
{
|
|
if (!TryReadUInt16(
|
|
ctx,
|
|
userDataAddress + 0x2E + (ulong)(resourceClass * sizeof(ushort)),
|
|
out resourceCounts[resourceClass]) ||
|
|
resourceCounts[resourceClass] > MaxMetadataEntries)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
var directResources = new Dictionary<uint, uint>();
|
|
if (directResourceCount != 0)
|
|
{
|
|
if (directResourceOffsetsAddress == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (uint type = 0; type < directResourceCount; type++)
|
|
{
|
|
if (!TryReadUInt16(ctx, directResourceOffsetsAddress + type * sizeof(ushort), out var offset))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (offset != ushort.MaxValue)
|
|
{
|
|
directResources[type] = offset;
|
|
}
|
|
}
|
|
}
|
|
|
|
var resources = new List<Gen5ShaderResourceMapping>();
|
|
for (var resourceClass = 0; resourceClass < ResourceClassCount; resourceClass++)
|
|
{
|
|
var count = resourceCounts[resourceClass];
|
|
if (count == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (resourceOffsets[resourceClass] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (uint slot = 0; slot < count; slot++)
|
|
{
|
|
if (!TryReadUInt16(
|
|
ctx,
|
|
resourceOffsets[resourceClass] + slot * sizeof(ushort),
|
|
out var sharp))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var offset = (uint)(sharp & 0x7FFF);
|
|
if (offset == 0x7FFF)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
resources.Add(new Gen5ShaderResourceMapping(
|
|
(Gen5ShaderResourceKind)resourceClass,
|
|
slot,
|
|
offset,
|
|
(sharp & 0x8000) != 0));
|
|
}
|
|
}
|
|
|
|
metadata = new Gen5ShaderMetadata(
|
|
extendedUserDataSize,
|
|
shaderResourceTableSize,
|
|
directResources,
|
|
resources);
|
|
return true;
|
|
}
|
|
|
|
private static bool TryReadUInt16(CpuContext ctx, ulong address, out ushort value)
|
|
{
|
|
Span<byte> bytes = stackalloc byte[sizeof(ushort)];
|
|
if (!ctx.Memory.TryRead(address, bytes))
|
|
{
|
|
value = 0;
|
|
return false;
|
|
}
|
|
|
|
value = BinaryPrimitives.ReadUInt16LittleEndian(bytes);
|
|
return true;
|
|
}
|
|
|
|
private static bool TryReadUInt64(CpuContext ctx, ulong address, out ulong value)
|
|
{
|
|
Span<byte> bytes = stackalloc byte[sizeof(ulong)];
|
|
if (!ctx.Memory.TryRead(address, bytes))
|
|
{
|
|
value = 0;
|
|
return false;
|
|
}
|
|
|
|
value = BinaryPrimitives.ReadUInt64LittleEndian(bytes);
|
|
return true;
|
|
}
|
|
}
|