mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-09 17:14:47 -06:00
Merge branch 'cemu-project:main' into main
This commit is contained in:
commit
36745d39ce
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -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
|
||||
|
||||
|
||||
@ -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));
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user