summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/audio/audren_u.cpp65
-rw-r--r--src/core/hle/service/audio/audren_u.h25
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp11
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h11
-rw-r--r--src/video_core/command_processor.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp112
6 files changed, 176 insertions, 49 deletions
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 38bc65d95..6e8002bc9 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/alignment.h"
#include "common/logging/log.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
@@ -256,12 +257,62 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
}
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ auto params = rp.PopRaw<WorkerBufferParameters>();
+
+ u64 buffer_sz = Common::AlignUp(4 * params.unknown8, 0x40);
+ buffer_sz += params.unknownC * 1024;
+ buffer_sz += 0x940 * (params.unknownC + 1);
+ buffer_sz += 0x3F0 * params.voice_count;
+ buffer_sz += Common::AlignUp(8 * (params.unknownC + 1), 0x10);
+ buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
+ buffer_sz +=
+ Common::AlignUp((0x3C0 * (params.sink_count + params.unknownC) + 4 * params.sample_count) *
+ (params.unknown8 + 6),
+ 0x40);
+
+ if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) {
+ u32 count = params.unknownC + 1;
+ u64 node_count = Common::AlignUp(count, 0x40);
+ u64 node_state_buffer_sz =
+ 4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8);
+ u64 edge_matrix_buffer_sz = 0;
+ node_count = Common::AlignUp(count * count, 0x40);
+ if (node_count >> 31 != 0) {
+ edge_matrix_buffer_sz = (node_count | 7) / 8;
+ } else {
+ edge_matrix_buffer_sz = node_count / 8;
+ }
+ buffer_sz += Common::AlignUp(node_state_buffer_sz + edge_matrix_buffer_sz, 0x10);
+ }
+
+ buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50;
+ if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) {
+ buffer_sz += 0xE0 * params.unknown2c;
+ buffer_sz += 0x20 * params.splitter_count;
+ buffer_sz += Common::AlignUp(4 * params.unknown2c, 0x10);
+ }
+ buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count;
+ u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count +
+ ((params.voice_count * 256) | 0x40);
+
+ if (params.unknown1c >= 1) {
+ output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count +
+ 16 * params.voice_count + 16) +
+ 0x658) *
+ (params.unknown1c + 1) +
+ 0xc0,
+ 0x40) +
+ output_sz;
+ }
+ output_sz = Common::AlignUp(output_sz + 0x1807e, 0x1000);
+
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
- rb.Push<u64>(0x4000);
+ rb.Push<u64>(output_sz);
- NGLOG_WARNING(Service_Audio, "(STUBBED) called");
+ NGLOG_DEBUG(Service_Audio, "called, buffer_size=0x{:X}", output_sz);
}
void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
@@ -273,4 +324,14 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
NGLOG_DEBUG(Service_Audio, "called");
}
+bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
+ u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
+ switch (feature) {
+ case AudioFeatures::Splitter:
+ return version_num >= 2;
+ default:
+ return false;
+ }
+}
+
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index 71b632e80..fe53de4ce 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -21,6 +21,31 @@ private:
void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
void GetAudioDevice(Kernel::HLERequestContext& ctx);
+
+ struct WorkerBufferParameters {
+ u32_le sample_rate;
+ u32_le sample_count;
+ u32_le unknown8;
+ u32_le unknownC;
+ u32_le voice_count;
+ u32_le sink_count;
+ u32_le effect_count;
+ u32_le unknown1c;
+ u8 unknown20;
+ u8 padding1[3];
+ u32_le splitter_count;
+ u32_le unknown2c;
+ u8 padding2[4];
+ u32_le magic;
+ };
+ static_assert(sizeof(WorkerBufferParameters) == 52,
+ "WorkerBufferParameters is an invalid size");
+
+ enum class AudioFeatures : u32 {
+ Splitter,
+ };
+
+ bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const;
};
} // namespace Service::Audio
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 be6b88f98..a9538ff43 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -24,6 +24,8 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
return ZCullGetCtxSize(input, output);
case IoctlCommand::IocZcullGetInfo:
return ZCullGetInfo(input, output);
+ case IoctlCommand::IocZbcSetTable:
+ return ZBCSetTable(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
@@ -125,4 +127,13 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
+u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) {
+ NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
+ IoctlZbcSetTable params{};
+ std::memcpy(&params, input.data(), input.size());
+ // TODO(ogniK): What does this even actually do?
+ std::memcpy(output.data(), &params, output.size());
+ return 0;
+}
+
} // namespace Service::Nvidia::Devices
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 2d43598b1..1d5ba2e67 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -25,6 +25,7 @@ private:
IocGetActiveSlotMaskCommand = 0x80084714,
IocZcullGetCtxSizeCommand = 0x80044701,
IocZcullGetInfo = 0x80284702,
+ IocZbcSetTable = 0x402C4703,
};
struct IoctlGpuCharacteristics {
@@ -117,11 +118,21 @@ private:
static_assert(sizeof(IoctlNvgpuGpuZcullGetInfoArgs) == 40,
"IoctlNvgpuGpuZcullGetInfoArgs is incorrect size");
+ struct IoctlZbcSetTable {
+ u32_le color_ds[4];
+ u32_le color_l2[4];
+ u32_le depth;
+ u32_le format;
+ u32_le type;
+ };
+ static_assert(sizeof(IoctlZbcSetTable) == 44, "IoctlZbcSetTable is incorrect size");
+
u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output);
+ u32 ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 2eaece298..d72d6f760 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -36,7 +36,6 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
if (method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id.
NGLOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
- ASSERT(bound_engines.find(subchannel) == bound_engines.end());
bound_engines[subchannel] = static_cast<EngineID>(value);
return;
}
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 1aa24da46..d24b1ab44 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -597,6 +597,46 @@ private:
return variable;
}
+ /**
+ * Returns the comparison string to use to compare two values in the 'set' family of
+ * instructions.
+ * @params condition The condition used in the 'set'-family instruction.
+ * @returns String corresponding to the GLSL operator that matches the desired comparison.
+ */
+ std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const {
+ using Tegra::Shader::PredCondition;
+ static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = {
+ {PredCondition::LessThan, "<"},
+ {PredCondition::Equal, "=="},
+ {PredCondition::LessEqual, "<="},
+ {PredCondition::GreaterThan, ">"},
+ };
+
+ auto comparison = PredicateComparisonStrings.find(condition);
+ ASSERT_MSG(comparison != PredicateComparisonStrings.end(),
+ "Unknown predicate comparison operation");
+ return comparison->second;
+ }
+
+ /**
+ * Returns the operator string to use to combine two predicates in the 'setp' family of
+ * instructions.
+ * @params operation The operator used in the 'setp'-family instruction.
+ * @returns String corresponding to the GLSL operator that matches the desired operator.
+ */
+ std::string GetPredicateCombiner(Tegra::Shader::PredOperation operation) const {
+ using Tegra::Shader::PredOperation;
+ static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = {
+ {PredOperation::And, "&&"},
+ {PredOperation::Or, "||"},
+ {PredOperation::Xor, "^^"},
+ };
+
+ auto op = PredicateOperationStrings.find(operation);
+ ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation");
+ return op->second;
+ }
+
/*
* Returns whether the instruction at the specified offset is a 'sched' instruction.
* Sched instructions always appear before a sequence of 3 instructions.
@@ -888,28 +928,25 @@ private:
}
using Tegra::Shader::Pred;
- ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) &&
- instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex),
- "Compound predicates are not implemented");
-
// We can't use the constant predicate as destination.
ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
- using Tegra::Shader::PredCondition;
- switch (instr.fsetp.cond) {
- case PredCondition::LessThan:
- SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')');
- break;
- case PredCondition::Equal:
- SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')');
- break;
- case PredCondition::LessEqual:
- SetPredicate(instr.fsetp.pred3, '(' + op_a + ") <= (" + op_b + ')');
- break;
- default:
- NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
- static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b);
- UNREACHABLE();
+ std::string second_pred =
+ GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
+
+ std::string comparator = GetPredicateComparison(instr.fsetp.cond);
+ std::string combiner = GetPredicateCombiner(instr.fsetp.op);
+
+ std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')';
+ // Set the primary predicate to the result of Predicate OP SecondPredicate
+ SetPredicate(instr.fsetp.pred3,
+ '(' + predicate + ") " + combiner + " (" + second_pred + ')');
+
+ if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
+ // Set the secondary predicate to the result of !Predicate OP SecondPredicate, if
+ // enabled
+ SetPredicate(instr.fsetp.pred0,
+ "!(" + predicate + ") " + combiner + " (" + second_pred + ')');
}
break;
}
@@ -941,35 +978,18 @@ private:
op_b = "abs(" + op_b + ')';
}
- using Tegra::Shader::Pred;
- ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex),
- "Compound predicates are not implemented");
-
// The fset instruction sets a register to 1.0 if the condition is true, and to 0
// otherwise.
- using Tegra::Shader::PredCondition;
- switch (instr.fset.cond) {
- case PredCondition::LessThan:
- regs.SetRegisterToFloat(instr.gpr0, 0,
- "((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1);
- break;
- case PredCondition::Equal:
- regs.SetRegisterToFloat(instr.gpr0, 0,
- "((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1);
- break;
- case PredCondition::LessEqual:
- regs.SetRegisterToFloat(instr.gpr0, 0,
- "((" + op_a + ") <= (" + op_b + ")) ? 1.0 : 0", 1, 1);
- break;
- case PredCondition::GreaterThan:
- regs.SetRegisterToFloat(instr.gpr0, 0,
- "((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1);
- break;
- default:
- NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
- static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b);
- UNREACHABLE();
- }
+ std::string second_pred =
+ GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
+
+ std::string comparator = GetPredicateComparison(instr.fset.cond);
+ std::string combiner = GetPredicateCombiner(instr.fset.op);
+
+ std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " +
+ combiner + " (" + second_pred + "))";
+
+ regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
break;
}
default: {