Merge branch 'cemu-project:main' into main

This commit is contained in:
Eddy 2026-06-30 19:16:20 +02:00 committed by GitHub
commit 36745d39ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 152 additions and 9 deletions

View File

@ -230,6 +230,9 @@ jobs:
- name: "Install system dependencies"
run: |
# Removing azure/bicep and aws to silence warnings in Github Actions
brew uninstall bicep
brew untap aws/tap azure/bicep
brew update
brew install nasm automake libtool

View File

@ -745,6 +745,31 @@ void MetalRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIn
}
}
MTL::BlitOption GetBlitOptionForTexture(const LatteTextureMtl* texture) {
switch (texture->GetTexture()->pixelFormat()) {
case MTL::PixelFormatDepth16Unorm:
case MTL::PixelFormatDepth32Float:
return MTL::BlitOptionDepthFromDepthStencil;
case MTL::PixelFormatStencil8:
return MTL::BlitOptionStencilFromDepthStencil;
case MTL::PixelFormatDepth24Unorm_Stencil8:
case MTL::PixelFormatDepth32Float_Stencil8:
// Can't copy both in one call — caller must specify.
// Default to depth
return MTL::BlitOptionDepthFromDepthStencil;
default:
return MTL::BlitOptionNone;
}
}
bool IsDepthStencilFormat(MTL::PixelFormat format) {
return format == MTL::PixelFormatDepth24Unorm_Stencil8 ||
format == MTL::PixelFormatDepth32Float_Stencil8;
}
// TODO: do a cpu copy on Apple Silicon?
void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize)
{
@ -774,9 +799,14 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
memcpy(allocation.memPtr, pixelData, compressedImageSize);
bufferAllocator.FlushReservation(allocation);
// TODO: specify blit options when copying to a depth stencil texture?
// Copy the data from the temporary buffer to the texture
blitCommandEncoder->copyFromBuffer(allocation.mtlBuffer, allocation.bufferOffset, bytesPerRow, 0, MTL::Size(width, height, 1), textureMtl->GetTexture(), sliceIndex, mipIndex, MTL::Origin(0, 0, offsetZ));
if (IsDepthStencilFormat(textureMtl->GetTexture()->pixelFormat())) {
// Metal doesn't allow copying depth and stencil data at the same time, so we need to do two copies for combined depth/stencil formats
blitCommandEncoder->copyFromBuffer(allocation.mtlBuffer, allocation.bufferOffset, bytesPerRow, 0, MTL::Size(width, height, 1), textureMtl->GetTexture(), sliceIndex, mipIndex, MTL::Origin(0, 0, offsetZ), MTL::BlitOptionDepthFromDepthStencil);
blitCommandEncoder->copyFromBuffer(allocation.mtlBuffer, allocation.bufferOffset, bytesPerRow, 0, MTL::Size(width, height, 1), textureMtl->GetTexture(), sliceIndex, mipIndex, MTL::Origin(0, 0, offsetZ), MTL::BlitOptionStencilFromDepthStencil);
} else {
blitCommandEncoder->copyFromBuffer(allocation.mtlBuffer, allocation.bufferOffset, bytesPerRow, 0, MTL::Size(width, height, 1), textureMtl->GetTexture(), sliceIndex, mipIndex, MTL::Origin(0, 0, offsetZ), GetBlitOptionForTexture(textureMtl));
}
//}
}

View File

@ -189,9 +189,114 @@ namespace H264
return H264DEC_STATUS::BAD_STREAM;
}
struct H264Dec_SeqParameterSet
{
// for now this contains only the fields we care about
uint32 pic_width_in_luma_samples{};
uint32 pic_height_in_map_units_x16{};
uint8 frame_mbs_only_flag{};
};
void H264Dec_parseScalingList(RBSPInputBitstream& stream, sint32 size)
{
sint32 lastScale = 8;
sint32 nextScale = 8;
for (sint32 i = 0; i < size; i++)
{
if (nextScale != 0)
{
sint32 deltaScale = stream.readSV_E();
nextScale = (lastScale + deltaScale + 256) % 256;
}
if (nextScale != 0)
lastScale = nextScale;
}
}
bool H264Dec_parseSequencePS(RBSPInputBitstream& stream, H264Dec_SeqParameterSet& ps)
{
ps = {};
uint32 profileIdc = stream.readBits<8>();
if (profileIdc != 66 && profileIdc != 77 && profileIdc != 100)
return false;
stream.readBits<8>(); // constraint_set flags
stream.readBits<8>(); // level_idc
uint32 seqParameterSetId = stream.readUV_E();
if (seqParameterSetId >= 32)
return false;
if (profileIdc == 100)
{
uint32 chromaFormatIdc = stream.readUV_E();
if (chromaFormatIdc > 1)
return false;
stream.readUV_E(); // bit_depth_luma_minus8
stream.readUV_E(); // bit_depth_chroma_minus8
stream.readBit(); // qpprime_y_zero_transform_bypass_flag
if (stream.readBit()) // seq_scaling_matrix_present_flag
{
for (sint32 i = 0; i < 8; i++)
{
if (stream.readBit())
H264Dec_parseScalingList(stream, i < 6 ? 16 : 64);
}
}
}
uint32 log2MaxFrameNumMinus4 = stream.readUV_E();
if (log2MaxFrameNumMinus4 > 12)
return false;
uint32 picOrderCntType = stream.readUV_E();
if (picOrderCntType > 2)
return false;
if (picOrderCntType == 0)
{
uint32 log2MaxPicOrderCntLsbMinus4 = stream.readUV_E();
if (log2MaxPicOrderCntLsbMinus4 > 12)
return false;
}
else if (picOrderCntType == 1)
{
stream.readBit(); // delta_pic_order_always_zero_flag
stream.readSV_E(); // offset_for_non_ref_pic
stream.readSV_E(); // offset_for_top_to_bottom_field
uint32 numRefFramesInPicOrderCntCycle = stream.readUV_E();
if (numRefFramesInPicOrderCntCycle > 0xFF)
return false;
for (uint32 i = 0; i < numRefFramesInPicOrderCntCycle; i++)
stream.readSV_E();
}
uint32 maxNumRefFrames = stream.readUV_E();
if (maxNumRefFrames > 16)
return false;
stream.readBit(); // gaps_in_frame_num_value_allowed_flag
uint32 picWidthInMbsMinus1 = stream.readUV_E();
uint32 width = 16 * (picWidthInMbsMinus1 + 1);
if ((width & 0xFFF0) < 0x10)
return false;
uint32 picHeightInMapUnitsMinus1 = stream.readUV_E();
uint32 heightInMapUnitsX16 = 16 * (picHeightInMapUnitsMinus1 + 1);
if ((heightInMapUnitsX16 & 0xFFF0) < 0x10)
return false;
ps.pic_width_in_luma_samples = width;
ps.pic_height_in_map_units_x16 = heightInMapUnitsX16;
ps.frame_mbs_only_flag = stream.readBit();
if (!ps.frame_mbs_only_flag)
stream.readBit(); // mb_adaptive_frame_field_flag
stream.readBit(); // direct_8x8_inference_flag
if (stream.readBit()) // frame_cropping_flag
{
stream.readUV_E(); // frame_crop_left_offset
stream.readUV_E(); // frame_crop_right_offset
stream.readUV_E(); // frame_crop_top_offset
stream.readUV_E(); // frame_crop_bottom_offset
}
stream.readBit(); // vui_parameters_present_flag
// vui parsing unnecessary as we currently dont need any of the fields
return true;
}
H264DEC_STATUS H264DECGetImageSize(uint8* stream, sint32 streamSize, sint32 offset, uint32be* outputWidth, uint32be* outputHeight)
{
if (!stream || streamSize < 4 || offset < 0 || !outputWidth || !outputHeight || offset < streamSize)
if (!stream || streamSize < 4 || offset < 0 || !outputWidth || !outputHeight || offset >= streamSize)
return H264DEC_STATUS::INVALID_PARAM;
if ( (offset+4) >= streamSize )
return H264DEC_STATUS::INVALID_PARAM;
@ -217,15 +322,19 @@ namespace H264
cur++;
continue;
}
h264State_seq_parameter_set_t psp;
bool r = h264Parser_ParseSPS(cur+2, end-cur-2, psp);
uint8* spsStart = cur + 2;
uint32 spsLength = (uint32)(end - spsStart);
H264Dec_SeqParameterSet psp;
RBSPInputBitstream rbspStream(spsStart, spsLength, false);
bool r = H264Dec_parseSequencePS(rbspStream, psp);
if(!r)
{
cemuLog_log(LogType::Force, "H264DECGetImageSize: Invalid SPS data");
cemu_assert_suspicious(); // should not happen
return H264DEC_STATUS::BAD_STREAM;
}
*outputWidth = (psp.pic_width_in_mbs_minus1 + 1) * 16;
*outputHeight = (psp.pic_height_in_map_units_minus1 + 1) * 16;
*outputWidth = psp.pic_width_in_luma_samples;
*outputHeight = psp.pic_height_in_map_units_x16;
if (!psp.frame_mbs_only_flag)
*outputHeight *= 2;
if (!*outputHeight || !*outputWidth)

View File

@ -7,7 +7,7 @@ class RBSPInputBitstream
public:
RBSPInputBitstream() {};
RBSPInputBitstream(uint8* stream, uint32 length)
RBSPInputBitstream(uint8* stream, uint32 length, bool removeEmulationByte = true) : m_removeEmulationByte(removeEmulationByte)
{
this->streamPtr = stream;
this->streamLength = length;
@ -169,7 +169,7 @@ private:
void _nextRBSPByte()
{
readIndex += sizeof(uint8);
if (readIndex >= 2 && streamPtr[readIndex - 2] == 0x00 && streamPtr[readIndex - 1] == 0x00 && streamPtr[readIndex] == 0x03)
if (readIndex >= 2 && streamPtr[readIndex - 2] == 0x00 && streamPtr[readIndex - 1] == 0x00 && streamPtr[readIndex] == 0x03 && m_removeEmulationByte)
{
readIndex += 1;
currentRBSPByte = streamPtr[readIndex];
@ -188,6 +188,7 @@ private:
uint8 currentRBSPByte{};
sint32 bitIndex{};
bool errorFlag{};
bool m_removeEmulationByte{};
};
class NALInputBitstream