mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-15 11:25:13 +00:00
ajm: added stubbed statistics instance (#1924)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions
* ajm: added stubbed statistics instance * fixed a typo, thanks poly * fixed clang-format * removed unused struct * small fixes * fixed typedefs, added per codec statistics
This commit is contained in:
parent
f09a95453e
commit
ee72d99947
|
@ -189,6 +189,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
|||
src/core/libraries/ajm/ajm_context.cpp
|
||||
src/core/libraries/ajm/ajm_context.h
|
||||
src/core/libraries/ajm/ajm_error.h
|
||||
src/core/libraries/ajm/ajm_instance_statistics.cpp
|
||||
src/core/libraries/ajm/ajm_instance_statistics.h
|
||||
src/core/libraries/ajm/ajm_instance.cpp
|
||||
src/core/libraries/ajm/ajm_instance.h
|
||||
src/core/libraries/ajm/ajm_mp3.cpp
|
||||
|
|
|
@ -183,13 +183,15 @@ int PS4_SYSV_ABI sceAjmInstanceSwitch() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAjmMemoryRegister() {
|
||||
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
||||
int PS4_SYSV_ABI sceAjmMemoryRegister(u32 context_id, void* ptr, size_t num_pages) {
|
||||
// All memory is already shared with our implementation since we do not use any hardware.
|
||||
LOG_TRACE(Lib_Ajm, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAjmMemoryUnregister() {
|
||||
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
||||
int PS4_SYSV_ABI sceAjmMemoryUnregister(u32 context_id, void* ptr) {
|
||||
// All memory is already shared with our implementation since we do not use any hardware.
|
||||
LOG_TRACE(Lib_Ajm, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,26 @@ union AjmJobFlags {
|
|||
};
|
||||
};
|
||||
|
||||
enum class AjmStatisticsFlags : u64 {
|
||||
Memory = 1 << 0,
|
||||
EnginePerCodec = 1 << 15,
|
||||
Engine = 1 << 16,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(AjmStatisticsFlags)
|
||||
|
||||
union AjmStatisticsJobFlags {
|
||||
AjmStatisticsJobFlags(AjmJobFlags job_flags) : raw(job_flags.raw) {}
|
||||
|
||||
u64 raw;
|
||||
struct {
|
||||
u64 version : 3;
|
||||
u64 : 12;
|
||||
AjmStatisticsFlags statistics_flags : 17;
|
||||
u64 : 32;
|
||||
};
|
||||
};
|
||||
static_assert(sizeof(AjmStatisticsJobFlags) == 8);
|
||||
|
||||
struct AjmSidebandResult {
|
||||
s32 result;
|
||||
s32 internal_result;
|
||||
|
@ -126,6 +146,31 @@ union AjmSidebandInitParameters {
|
|||
u8 reserved[8];
|
||||
};
|
||||
|
||||
struct AjmSidebandStatisticsEngine {
|
||||
float usage_batch;
|
||||
float usage_interval[3];
|
||||
};
|
||||
|
||||
struct AjmSidebandStatisticsEnginePerCodec {
|
||||
u8 codec_count;
|
||||
u8 codec_id[3];
|
||||
float codec_percentage[3];
|
||||
};
|
||||
|
||||
struct AjmSidebandStatisticsMemory {
|
||||
u32 instance_free;
|
||||
u32 buffer_free;
|
||||
u32 batch_size;
|
||||
u32 input_size;
|
||||
u32 output_size;
|
||||
u32 small_size;
|
||||
};
|
||||
|
||||
struct AjmSidebandStatisticsEngineParameters {
|
||||
u32 interval_count;
|
||||
float interval[3];
|
||||
};
|
||||
|
||||
union AjmInstanceFlags {
|
||||
u64 raw;
|
||||
struct {
|
||||
|
@ -178,8 +223,8 @@ int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmI
|
|||
int PS4_SYSV_ABI sceAjmInstanceDestroy(u32 context, u32 instance);
|
||||
int PS4_SYSV_ABI sceAjmInstanceExtend();
|
||||
int PS4_SYSV_ABI sceAjmInstanceSwitch();
|
||||
int PS4_SYSV_ABI sceAjmMemoryRegister();
|
||||
int PS4_SYSV_ABI sceAjmMemoryUnregister();
|
||||
int PS4_SYSV_ABI sceAjmMemoryRegister(u32 context_id, void* ptr, size_t num_pages);
|
||||
int PS4_SYSV_ABI sceAjmMemoryUnregister(u32 context_id, void* ptr);
|
||||
int PS4_SYSV_ABI sceAjmModuleRegister(u32 context, AjmCodecType codec_type, s64 reserved);
|
||||
int PS4_SYSV_ABI sceAjmModuleUnregister();
|
||||
int PS4_SYSV_ABI sceAjmStrError();
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
: m_p_begin(begin), m_p_current(m_p_begin), m_size(size) {}
|
||||
AjmBatchBuffer(std::span<u8> data)
|
||||
: m_p_begin(data.data()), m_p_current(m_p_begin), m_size(data.size()) {}
|
||||
AjmBatchBuffer(AjmChunkBuffer& buffer)
|
||||
: AjmBatchBuffer(reinterpret_cast<u8*>(buffer.p_address), buffer.size) {}
|
||||
|
||||
AjmBatchBuffer SubBuffer(size_t size = s_dynamic_extent) {
|
||||
auto current = m_p_current;
|
||||
|
@ -113,6 +115,88 @@ private:
|
|||
size_t m_size{};
|
||||
};
|
||||
|
||||
AjmJob AjmStatisticsJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
||||
std::optional<AjmJobFlags> job_flags = {};
|
||||
std::optional<AjmChunkBuffer> input_control_buffer = {};
|
||||
std::optional<AjmChunkBuffer> output_control_buffer = {};
|
||||
|
||||
AjmJob job;
|
||||
job.instance_id = instance_id;
|
||||
|
||||
while (!batch_buffer.IsEmpty()) {
|
||||
auto& header = batch_buffer.Peek<AjmChunkHeader>();
|
||||
switch (header.ident) {
|
||||
case Identifier::AjmIdentInputControlBuf: {
|
||||
ASSERT_MSG(!input_control_buffer.has_value(),
|
||||
"Only one instance of input control buffer is allowed per job");
|
||||
const auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||
if (buffer.p_address != nullptr && buffer.size != 0) {
|
||||
input_control_buffer = buffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Identifier::AjmIdentControlFlags: {
|
||||
ASSERT_MSG(!job_flags.has_value(), "Only one instance of job flags is allowed per job");
|
||||
auto& chunk = batch_buffer.Consume<AjmChunkFlags>();
|
||||
job_flags = AjmJobFlags{
|
||||
.raw = (u64(chunk.header.payload) << 32) + chunk.flags_low,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case Identifier::AjmIdentReturnAddressBuf: {
|
||||
// Ignore return address buffers.
|
||||
batch_buffer.Skip<AjmChunkBuffer>();
|
||||
break;
|
||||
}
|
||||
case Identifier::AjmIdentOutputControlBuf: {
|
||||
ASSERT_MSG(!output_control_buffer.has_value(),
|
||||
"Only one instance of output control buffer is allowed per job");
|
||||
const auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||
if (buffer.p_address != nullptr && buffer.size != 0) {
|
||||
output_control_buffer = buffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE_MSG("Unknown chunk: {}", header.ident);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(job_flags.has_value());
|
||||
job.flags = job_flags.value();
|
||||
|
||||
AjmStatisticsJobFlags flags(job.flags);
|
||||
if (input_control_buffer.has_value()) {
|
||||
AjmBatchBuffer input_batch(input_control_buffer.value());
|
||||
if (True(flags.statistics_flags & AjmStatisticsFlags::Engine)) {
|
||||
job.input.statistics_engine_parameters =
|
||||
input_batch.Consume<AjmSidebandStatisticsEngineParameters>();
|
||||
}
|
||||
}
|
||||
|
||||
if (output_control_buffer.has_value()) {
|
||||
AjmBatchBuffer output_batch(output_control_buffer.value());
|
||||
job.output.p_result = &output_batch.Consume<AjmSidebandResult>();
|
||||
*job.output.p_result = AjmSidebandResult{};
|
||||
|
||||
if (True(flags.statistics_flags & AjmStatisticsFlags::Engine)) {
|
||||
job.output.p_engine = &output_batch.Consume<AjmSidebandStatisticsEngine>();
|
||||
*job.output.p_engine = AjmSidebandStatisticsEngine{};
|
||||
}
|
||||
if (True(flags.statistics_flags & AjmStatisticsFlags::EnginePerCodec)) {
|
||||
job.output.p_engine_per_codec =
|
||||
&output_batch.Consume<AjmSidebandStatisticsEnginePerCodec>();
|
||||
*job.output.p_engine_per_codec = AjmSidebandStatisticsEnginePerCodec{};
|
||||
}
|
||||
if (True(flags.statistics_flags & AjmStatisticsFlags::Memory)) {
|
||||
job.output.p_memory = &output_batch.Consume<AjmSidebandStatisticsMemory>();
|
||||
*job.output.p_memory = AjmSidebandStatisticsMemory{};
|
||||
}
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
||||
std::optional<AjmJobFlags> job_flags = {};
|
||||
std::optional<AjmChunkBuffer> input_control_buffer = {};
|
||||
|
@ -155,15 +239,6 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
|||
batch_buffer.Skip<AjmChunkBuffer>();
|
||||
break;
|
||||
}
|
||||
case Identifier::AjmIdentInlineBuf: {
|
||||
ASSERT_MSG(!output_control_buffer.has_value(),
|
||||
"Only one instance of inline buffer is allowed per job");
|
||||
const auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||
if (buffer.p_address != nullptr && buffer.size != 0) {
|
||||
inline_buffer = buffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Identifier::AjmIdentOutputRunBuf: {
|
||||
auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||
u8* p_begin = reinterpret_cast<u8*>(buffer.p_address);
|
||||
|
@ -186,13 +261,12 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
ASSERT(job_flags.has_value());
|
||||
job.flags = job_flags.value();
|
||||
|
||||
// Initialize sideband input parameters
|
||||
if (input_control_buffer.has_value()) {
|
||||
AjmBatchBuffer input_batch(reinterpret_cast<u8*>(input_control_buffer->p_address),
|
||||
input_control_buffer->size);
|
||||
|
||||
AjmBatchBuffer input_batch(input_control_buffer.value());
|
||||
const auto sideband_flags = job_flags->sideband_flags;
|
||||
if (True(sideband_flags & AjmJobSidebandFlags::Format) && !input_batch.IsEmpty()) {
|
||||
job.input.format = input_batch.Consume<AjmSidebandFormat>();
|
||||
|
@ -202,6 +276,9 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
|||
}
|
||||
|
||||
const auto control_flags = job_flags.value().control_flags;
|
||||
if (True(control_flags & AjmJobControlFlags::Resample)) {
|
||||
job.input.resample_parameters = input_batch.Consume<AjmSidebandResampleParameters>();
|
||||
}
|
||||
if (True(control_flags & AjmJobControlFlags::Initialize)) {
|
||||
job.input.init_params = AjmDecAt9InitializeParameters{};
|
||||
std::memcpy(&job.input.init_params.value(), input_batch.GetCurrent(),
|
||||
|
@ -209,21 +286,9 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
if (inline_buffer.has_value()) {
|
||||
AjmBatchBuffer inline_batch(reinterpret_cast<u8*>(inline_buffer->p_address),
|
||||
inline_buffer->size);
|
||||
|
||||
const auto control_flags = job_flags.value().control_flags;
|
||||
if (True(control_flags & AjmJobControlFlags::Resample)) {
|
||||
job.input.resample_parameters = inline_batch.Consume<AjmSidebandResampleParameters>();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize sideband output parameters
|
||||
if (output_control_buffer.has_value()) {
|
||||
AjmBatchBuffer output_batch(reinterpret_cast<u8*>(output_control_buffer->p_address),
|
||||
output_control_buffer->size);
|
||||
|
||||
AjmBatchBuffer output_batch(output_control_buffer.value());
|
||||
job.output.p_result = &output_batch.Consume<AjmSidebandResult>();
|
||||
*job.output.p_result = AjmSidebandResult{};
|
||||
|
||||
|
@ -260,9 +325,21 @@ std::shared_ptr<AjmBatch> AjmBatch::FromBatchBuffer(std::span<u8> data) {
|
|||
AjmBatchBuffer buffer(data);
|
||||
while (!buffer.IsEmpty()) {
|
||||
auto& job_chunk = buffer.Consume<AjmChunkJob>();
|
||||
if (job_chunk.header.ident == AjmIdentInlineBuf) {
|
||||
// Inline buffers are used to store sideband input data.
|
||||
// We should just skip them as they do not require any special handling.
|
||||
buffer.Advance(job_chunk.size);
|
||||
continue;
|
||||
}
|
||||
ASSERT(job_chunk.header.ident == AjmIdentJob);
|
||||
auto instance_id = job_chunk.header.payload;
|
||||
batch->jobs.push_back(AjmJobFromBatchBuffer(instance_id, buffer.SubBuffer(job_chunk.size)));
|
||||
if (instance_id == AJM_INSTANCE_STATISTICS) {
|
||||
batch->jobs.push_back(
|
||||
AjmStatisticsJobFromBatchBuffer(instance_id, buffer.SubBuffer(job_chunk.size)));
|
||||
} else {
|
||||
batch->jobs.push_back(
|
||||
AjmJobFromBatchBuffer(instance_id, buffer.SubBuffer(job_chunk.size)));
|
||||
}
|
||||
}
|
||||
|
||||
return batch;
|
||||
|
|
|
@ -23,6 +23,7 @@ struct AjmJob {
|
|||
struct Input {
|
||||
std::optional<AjmDecAt9InitializeParameters> init_params;
|
||||
std::optional<AjmSidebandResampleParameters> resample_parameters;
|
||||
std::optional<AjmSidebandStatisticsEngineParameters> statistics_engine_parameters;
|
||||
std::optional<AjmSidebandFormat> format;
|
||||
std::optional<AjmSidebandGaplessDecode> gapless_decode;
|
||||
std::vector<u8> buffer;
|
||||
|
@ -33,6 +34,9 @@ struct AjmJob {
|
|||
AjmSidebandResult* p_result = nullptr;
|
||||
AjmSidebandStream* p_stream = nullptr;
|
||||
AjmSidebandFormat* p_format = nullptr;
|
||||
AjmSidebandStatisticsMemory* p_memory = nullptr;
|
||||
AjmSidebandStatisticsEnginePerCodec* p_engine_per_codec = nullptr;
|
||||
AjmSidebandStatisticsEngine* p_engine = nullptr;
|
||||
AjmSidebandGaplessDecode* p_gapless_decode = nullptr;
|
||||
AjmSidebandMFrame* p_mframe = nullptr;
|
||||
u8* p_codec_info = nullptr;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "core/libraries/ajm/ajm_context.h"
|
||||
#include "core/libraries/ajm/ajm_error.h"
|
||||
#include "core/libraries/ajm/ajm_instance.h"
|
||||
#include "core/libraries/ajm/ajm_instance_statistics.h"
|
||||
#include "core/libraries/ajm/ajm_mp3.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
||||
|
@ -70,15 +71,19 @@ void AjmContext::ProcessBatch(u32 id, std::span<AjmJob> jobs) {
|
|||
LOG_TRACE(Lib_Ajm, "Processing job {} for instance {}. flags = {:#x}", id, job.instance_id,
|
||||
job.flags.raw);
|
||||
|
||||
std::shared_ptr<AjmInstance> instance;
|
||||
{
|
||||
std::shared_lock lock(instances_mutex);
|
||||
auto* p_instance = instances.Get(job.instance_id);
|
||||
ASSERT_MSG(p_instance != nullptr, "Attempting to execute job on null instance");
|
||||
instance = *p_instance;
|
||||
}
|
||||
if (job.instance_id == AJM_INSTANCE_STATISTICS) {
|
||||
AjmInstanceStatistics::Getinstance().ExecuteJob(job);
|
||||
} else {
|
||||
std::shared_ptr<AjmInstance> instance;
|
||||
{
|
||||
std::shared_lock lock(instances_mutex);
|
||||
auto* p_instance = instances.Get(job.instance_id);
|
||||
ASSERT_MSG(p_instance != nullptr, "Attempting to execute job on null instance");
|
||||
instance = *p_instance;
|
||||
}
|
||||
|
||||
instance->ExecuteJob(job);
|
||||
instance->ExecuteJob(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,11 +68,11 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||
m_codec->Initialize(¶ms, sizeof(params));
|
||||
}
|
||||
if (job.input.resample_parameters.has_value()) {
|
||||
UNREACHABLE_MSG("Unimplemented: resample parameters");
|
||||
LOG_ERROR(Lib_Ajm, "Unimplemented: resample parameters");
|
||||
m_resample_parameters = job.input.resample_parameters.value();
|
||||
}
|
||||
if (job.input.format.has_value()) {
|
||||
UNREACHABLE_MSG("Unimplemented: format parameters");
|
||||
LOG_ERROR(Lib_Ajm, "Unimplemented: format parameters");
|
||||
m_format = job.input.format.value();
|
||||
}
|
||||
if (job.input.gapless_decode.has_value()) {
|
||||
|
|
37
src/core/libraries/ajm/ajm_instance_statistics.cpp
Normal file
37
src/core/libraries/ajm/ajm_instance_statistics.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/libraries/ajm/ajm.h"
|
||||
#include "core/libraries/ajm/ajm_instance_statistics.h"
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
||||
void AjmInstanceStatistics::ExecuteJob(AjmJob& job) {
|
||||
if (job.output.p_engine) {
|
||||
job.output.p_engine->usage_batch = 0.01;
|
||||
const auto ic = job.input.statistics_engine_parameters->interval_count;
|
||||
for (u32 idx = 0; idx < ic; ++idx) {
|
||||
job.output.p_engine->usage_interval[idx] = 0.01;
|
||||
}
|
||||
}
|
||||
if (job.output.p_engine_per_codec) {
|
||||
job.output.p_engine_per_codec->codec_count = 1;
|
||||
job.output.p_engine_per_codec->codec_id[0] = static_cast<u8>(AjmCodecType::At9Dec);
|
||||
job.output.p_engine_per_codec->codec_percentage[0] = 0.01;
|
||||
}
|
||||
if (job.output.p_memory) {
|
||||
job.output.p_memory->instance_free = 0x400000;
|
||||
job.output.p_memory->buffer_free = 0x400000;
|
||||
job.output.p_memory->batch_size = 0x4200;
|
||||
job.output.p_memory->input_size = 0x2000;
|
||||
job.output.p_memory->output_size = 0x2000;
|
||||
job.output.p_memory->small_size = 0x200;
|
||||
}
|
||||
}
|
||||
|
||||
AjmInstanceStatistics& AjmInstanceStatistics::Getinstance() {
|
||||
static AjmInstanceStatistics instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace Libraries::Ajm
|
17
src/core/libraries/ajm/ajm_instance_statistics.h
Normal file
17
src/core/libraries/ajm/ajm_instance_statistics.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/ajm/ajm_batch.h"
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
||||
class AjmInstanceStatistics {
|
||||
public:
|
||||
void ExecuteJob(AjmJob& job);
|
||||
|
||||
static AjmInstanceStatistics& Getinstance();
|
||||
};
|
||||
|
||||
} // namespace Libraries::Ajm
|
Loading…
Reference in a new issue