diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 1b8f575586..45a4a402da 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -35,6 +35,7 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span return WrapFixed(this, &nvhost_ctrl_gpu::ZBCSetTable, input, output); case 0x4: return WrapFixed(this, &nvhost_ctrl_gpu::ZBCQueryTable, input, output); + //deviation case 0x5: return WrapFixed(this, &nvhost_ctrl_gpu::GetCharacteristics1, input, output); case 0x6: @@ -50,7 +51,29 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span } break; } - UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + // still unimplemented + std::string_view friendly_name = [raw = command.raw]() { + switch (raw) { + case 0x0d: return "INVAL_ICACHE"; + case 0x0e: return "SET_MMU_DEBUG_MODE "; + case 0x0f: return "SET_SM_DEBUG_MODE"; + case 0x10: return "WAIT_FOR_PAUSE"; + case 0x11: return "GET_TPC_EXCEPTION_EN_STATUS"; + case 0x12: return "NUM_VSMS"; + case 0x13: return "VSMS_MAPPING"; + case 0x14: return "ZBC_GET_ACTIVE_SLOT_MASK"; + case 0x15: return "PMU_GET_GPU_LOAD"; + case 0x16: return "SET_CG_CONTROLS"; + case 0x17: return "GET_CG_CONTROLS"; + case 0x18: return "SET_PG_CONTROLS"; + case 0x19: return "GET_PG_CONTROLS"; + case 0x1A: return "PMU_GET_ELPG_RESIDENCY_GATING"; + case 0x1B: return "GET_ERROR_CHANNEL_USER_DATA"; + case 0x1D: return "GET_CPU_TIME_CORRELATION_INFO"; + default: return "UNKNOWN"; + } + }(); + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X} {}", command.raw, friendly_name); return NvResult::NotImplemented; } @@ -230,18 +253,70 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) { } NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) { - LOG_WARNING(Service_NVDRV, "(STUBBED) called"); + LOG_DEBUG(Service_NVDRV, "called"); + ZbcEntry entry = {}; + std::memset(&entry, 0, sizeof(entry)); // TODO(ogniK): What does this even actually do? + // TODO(myself): This thing I guess + if (params.type == 1) { + for (auto i = 0; i < 4; ++i) { + entry.color_ds[i] = params.color_ds[i]; + entry.color_l2[i] = params.color_l2[i]; + } + ASSERT(this->max_color_entries < 16); + this->color_entries[this->max_color_entries] = entry; + ++this->max_color_entries; + } else if (params.type == 2) { + entry.depth = params.depth; + ASSERT(this->max_depth_entries < 16); + this->depth_entries[this->max_depth_entries] = entry; + ++this->max_depth_entries; + } return NvResult::Success; } NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) { - LOG_WARNING(Service_NVDRV, "(STUBBED) called"); + LOG_DEBUG(Service_NVDRV, "called"); + struct ZbcQueryParams { + u32_le color_ds[4]; + u32_le color_l2[4]; + u32_le depth; + u32_le ref_cnt; + u32_le format; + u32_le type; + u32_le index_size; + } entry = {}; + std::memset(&entry, 0, sizeof(entry)); + auto const index = params.index_size; + if (params.type == 0) { //no + entry.index_size = 15; + } else if (params.type == 1) { //color + ASSERT(index < 16); + for (auto i = 0; i < 4; ++i) { + params.color_ds[i] = this->color_entries[index].color_ds[i]; + params.color_l2[i] = this->color_entries[index].color_l2[i]; + } + // TODO: Only if no error thrown (otherwise dont modify) + params.format = this->color_entries[index].format; + //params.ref_cnt = this->color_entries[index].ref_cnt; + } else if (params.type == 2) { //depth + ASSERT(index < 16); + params.depth = this->depth_entries[index].depth; + // TODO: Only if no error thrown (otherwise dont modify) + params.format = this->depth_entries[index].format; + //params.ref_cnt = this->depth_entries[index].ref_cnt; + } else { + UNREACHABLE(); + } return NvResult::Success; } NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) { - LOG_WARNING(Service_NVDRV, "(STUBBED) called"); + LOG_DEBUG(Service_NVDRV, "called 0x{:X}", params.flush); + // if ((params.flush & 0x01) != 0) //l2 flush + // /* we dont emulate l2 */; + // if ((params.flush & 0x04) != 0) //fb flush + // /* we dont emulate fb */; return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index d2ab05b214..c36fcbaa69 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -151,6 +151,16 @@ private: }; static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); + struct IoctlGetCpuTimeCorrelationInfo { + struct { + u64_le cpu_timestamp; + u64_le gpu_timestamp; + } samples[16]; + u32_le count; + u32_le source_id; + }; + static_assert(sizeof(IoctlGetCpuTimeCorrelationInfo) == 264); + NvResult GetCharacteristics1(IoctlCharacteristics& params); NvResult GetCharacteristics3(IoctlCharacteristics& params, std::span gpu_characteristics); @@ -171,6 +181,18 @@ private: // Events Kernel::KEvent* error_notifier_event; Kernel::KEvent* unknown_event; + + struct ZbcEntry { + u32_le color_ds[4]; + u32_le color_l2[4]; + u32_le depth; + u32_le type; + u32_le format; + }; + std::array color_entries; + std::array depth_entries; + u8 max_color_entries; + u8 max_depth_entries; }; } // namespace Service::Nvidia::Devices