diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index e87a0556..40b1f897 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -8,6 +8,7 @@ #include "common/slot_vector.h" #include "core/libraries/error_codes.h" #include "core/libraries/gnmdriver/gnmdriver.h" +#include "core/libraries/kernel/libkernel.h" #include "core/libraries/libs.h" #include "core/libraries/videoout/video_out.h" #include "core/platform.h" @@ -264,7 +265,9 @@ static_assert(CtxInitSequence400.size() == 0x61); // In case if `submitDone` is issued we need to block submissions until GPU idle static u32 submission_lock{}; static std::mutex m_submission{}; -static u64 frames_submitted{}; // frame counter +static u64 frames_submitted{}; // frame counter +static bool send_init_packet{true}; // initialize HW state before first game's submit in a frame +static int sdk_version{0}; struct AscQueueInfo { VAddr map_addr; @@ -1935,6 +1938,17 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[ submission_lock = 0; } + if (send_init_packet) { + if (sdk_version <= 0x1ffffffu) { + liverpool->SubmitGfx(InitSequence, {}); + } else if (sdk_version <= 0x3ffffffu) { + liverpool->SubmitGfx(InitSequence200, {}); + } else { + liverpool->SubmitGfx(InitSequence350, {}); + } + send_init_packet = false; + } + for (auto cbpair = 0u; cbpair < count; ++cbpair) { const auto* ccb = ccb_gpu_addrs ? ccb_gpu_addrs[cbpair] : nullptr; const auto ccb_size_in_bytes = ccb_sizes_in_bytes ? ccb_sizes_in_bytes[cbpair] : 0; @@ -1977,6 +1991,7 @@ int PS4_SYSV_ABI sceGnmSubmitDone() { submission_lock = true; } liverpool->NotifySubmitDone(); + send_init_packet = true; ++frames_submitted; return ORBIS_OK; } @@ -2450,6 +2465,11 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { liverpool = std::make_unique(); renderer = std::make_unique(*g_window, liverpool.get()); + const int result = sceKernelGetCompiledSdkVersion(&sdk_version); + if (result != ORBIS_OK) { + sdk_version = 0; + } + LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAreSubmitsAllowed); diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index e7e7d11d..fce0d621 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -154,7 +154,7 @@ int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver) { int version = param_sfo->GetInteger("SYSTEM_VER"); LOG_INFO(Kernel, "returned system version = {:#x}", version); *ver = version; - return ORBIS_OK; + return (version > 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL; } s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) { diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/libkernel.h index 0cc6b0b2..a33c6a71 100644 --- a/src/core/libraries/kernel/libkernel.h +++ b/src/core/libraries/kernel/libkernel.h @@ -28,6 +28,7 @@ typedef struct { } OrbisKernelUuid; int* PS4_SYSV_ABI __Error(); +int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver); void LibKernel_Register(Core::Loader::SymbolsResolver* sym); diff --git a/src/emulator.cpp b/src/emulator.cpp index 77ba91f0..09be9273 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -42,10 +42,6 @@ Emulator::Emulator() : window{WindowWidth, WindowHeight, controller} { // Start logger. Common::Log::Initialize(); Common::Log::Start(); - - // Initialize kernel and library facilities. - Libraries::Kernel::init_pthreads(); - Libraries::InitHLELibs(&linker->GetHLESymbols()); } Emulator::~Emulator() { @@ -93,6 +89,10 @@ void Emulator::Run(const std::filesystem::path& file) { const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id; mnt->Mount(mount_temp_dir, "/temp0"); // called in app_content ==> stat/mkdir + // Initialize kernel and library facilities. + Libraries::Kernel::init_pthreads(); + Libraries::InitHLELibs(&linker->GetHLESymbols()); + // Load the module with the linker linker->LoadModule(file); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index a6d4b770..71a09ea2 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -122,9 +122,8 @@ void PipelineCache::RefreshGraphicsKey() { key.depth.depth_enable.Assign(key.depth_format != vk::Format::eUndefined); } - // TODO: Should be a check for `OperationMode::Disable` once we emulate HW state init packet - // sent by system software. - const auto skip_cb_binding = false; + const auto skip_cb_binding = + regs.color_control.mode == AmdGpu::Liverpool::ColorControl::OperationMode::Disable; // `RenderingInfo` is assumed to be initialized with a contiguous array of valid color // attachments. This might be not a case as HW color buffers can be bound in an arbitrary order.