diff options
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 65 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.h | 25 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | 11 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 112 | 
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(¶ms, input.data(), input.size()); +    // TODO(ogniK): What does this even actually do? +    std::memcpy(output.data(), ¶ms, 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: { | 
