Compare commits
2 commits
14b0cd2904
...
b1ef551153
Author | SHA1 | Date | |
---|---|---|---|
b1ef551153 | |||
cf634d4d6f |
2 changed files with 119 additions and 60 deletions
|
@ -256,61 +256,103 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) {
|
|||
}
|
||||
|
||||
NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
|
||||
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];
|
||||
if (params.type > supported_types) {
|
||||
LOG_ERROR(Service_NVDRV, "ZBCSetTable: invalid type {:#X}", params.type);
|
||||
return NvResult::BadParameter;
|
||||
}
|
||||
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;
|
||||
|
||||
std::scoped_lock lk(zbc_mutex);
|
||||
|
||||
switch (static_cast<ZBCTypes>(params.type)) {
|
||||
case ZBCTypes::color: {
|
||||
ZbcColorEntry color_entry{};
|
||||
std::copy_n(std::begin(params.color_ds), color_entry.color_ds.size(), color_entry.color_ds.begin());
|
||||
std::copy_n(std::begin(params.color_l2), color_entry.color_l2.size(), color_entry.color_l2.begin());
|
||||
color_entry.format = params.format;
|
||||
color_entry.ref_cnt = 1u;
|
||||
|
||||
auto color_it = std::ranges::find_if(zbc_colors,
|
||||
[&](const ZbcColorEntry& color_in_question) {
|
||||
return color_entry.format == color_in_question.format &&
|
||||
color_entry.color_ds == color_in_question.color_ds &&
|
||||
color_entry.color_l2 == color_in_question.color_l2;
|
||||
});
|
||||
|
||||
if (color_it != zbc_colors.end()) {
|
||||
++color_it->ref_cnt;
|
||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused color entry fmt={:#X}, ref_cnt={:#X}",
|
||||
params.format, color_it->ref_cnt);
|
||||
} else {
|
||||
zbc_colors.push_back(color_entry);
|
||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added color entry fmt={:#X}, index={:#X}",
|
||||
params.format, zbc_colors.size() - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZBCTypes::depth: {
|
||||
ZbcDepthEntry depth_entry{params.depth, params.format, 1u};
|
||||
|
||||
auto depth_it = std::ranges::find_if(zbc_depths,
|
||||
[&](const ZbcDepthEntry& depth_entry_in_question) {
|
||||
return depth_entry.format == depth_entry_in_question.format &&
|
||||
depth_entry.depth == depth_entry_in_question.depth;
|
||||
});
|
||||
|
||||
if (depth_it != zbc_depths.end()) {
|
||||
++depth_it->ref_cnt;
|
||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused depth entry fmt={:#X}, ref_cnt={:#X}",
|
||||
depth_entry.format, depth_it->ref_cnt);
|
||||
} else {
|
||||
zbc_depths.push_back(depth_entry);
|
||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added depth entry fmt={:#X}, index={:#X}",
|
||||
depth_entry.format, zbc_depths.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NvResult::Success;
|
||||
}
|
||||
|
||||
NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
|
||||
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];
|
||||
if (params.type > supported_types) {
|
||||
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid type {:#X}", params.type);
|
||||
return NvResult::BadParameter;
|
||||
}
|
||||
// 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();
|
||||
|
||||
std::scoped_lock lk(zbc_mutex);
|
||||
|
||||
switch (static_cast<ZBCTypes>(params.type)) {
|
||||
case ZBCTypes::color: {
|
||||
if (params.index_size >= zbc_colors.size()) {
|
||||
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid color index {:#X}", params.index_size);
|
||||
return NvResult::BadParameter;
|
||||
}
|
||||
|
||||
const auto& colors = zbc_colors[params.index_size];
|
||||
std::copy_n(colors.color_ds.begin(), colors.color_ds.size(), std::begin(params.color_ds));
|
||||
std::copy_n(colors.color_l2.begin(), colors.color_l2.size(), std::begin(params.color_l2));
|
||||
params.depth = 0;
|
||||
params.ref_cnt = colors.ref_cnt;
|
||||
params.format = colors.format;
|
||||
params.index_size = static_cast<u32>(zbc_colors.size());
|
||||
break;
|
||||
}
|
||||
case ZBCTypes::depth: {
|
||||
if (params.index_size >= zbc_depths.size()) {
|
||||
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid depth index {:#X}", params.index_size);
|
||||
return NvResult::BadParameter;
|
||||
}
|
||||
|
||||
const auto& depth_entry = zbc_depths[params.index_size];
|
||||
std::fill(std::begin(params.color_ds), std::end(params.color_ds), 0);
|
||||
std::fill(std::begin(params.color_l2), std::end(params.color_l2), 0);
|
||||
params.depth = depth_entry.depth;
|
||||
params.ref_cnt = depth_entry.ref_cnt;
|
||||
params.format = depth_entry.format;
|
||||
params.index_size = static_cast<u32>(zbc_depths.size());
|
||||
}
|
||||
}
|
||||
|
||||
return NvResult::Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -34,6 +37,11 @@ public:
|
|||
Kernel::KEvent* QueryEvent(u32 event_id) override;
|
||||
|
||||
private:
|
||||
enum class ZBCTypes {
|
||||
color = 1,
|
||||
depth = 2,
|
||||
};
|
||||
|
||||
struct IoctlGpuCharacteristics {
|
||||
u32_le arch; // 0x120 (NVGPU_GPU_ARCH_GM200)
|
||||
u32_le impl; // 0xB (NVGPU_GPU_IMPL_GM20B)
|
||||
|
@ -139,6 +147,21 @@ private:
|
|||
};
|
||||
static_assert(sizeof(IoctlZbcQueryTable) == 52, "IoctlZbcQueryTable is incorrect size");
|
||||
|
||||
struct ZbcColorEntry {
|
||||
std::array<u32, 4> color_ds{};
|
||||
std::array<u32, 4> color_l2{};
|
||||
u32 format{};
|
||||
u32 ref_cnt{};
|
||||
};
|
||||
static_assert(sizeof(ZbcColorEntry) == 40, "ZbcColorEntry is incorrect size");
|
||||
|
||||
struct ZbcDepthEntry {
|
||||
u32 depth{};
|
||||
u32 format{};
|
||||
u32 ref_cnt{};
|
||||
};
|
||||
static_assert(sizeof(ZbcDepthEntry) == 12, "ZbcDepthEntry is incorrect size");
|
||||
|
||||
struct IoctlFlushL2 {
|
||||
u32_le flush; // l2_flush | l2_invalidate << 1 | fb_flush << 2
|
||||
u32_le reserved;
|
||||
|
@ -182,17 +205,11 @@ private:
|
|||
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<ZbcEntry, 16> color_entries;
|
||||
std::array<ZbcEntry, 16> depth_entries;
|
||||
u8 max_color_entries;
|
||||
u8 max_depth_entries;
|
||||
// ZBC Tables
|
||||
std::mutex zbc_mutex{};
|
||||
std::vector<ZbcColorEntry> zbc_colors{};
|
||||
std::vector<ZbcDepthEntry> zbc_depths{};
|
||||
const u32 supported_types = 2u;
|
||||
};
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue