diff options
-rw-r--r-- | src/core/hle/ipc.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/errors.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 27 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 13 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 30 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 20 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 4 | ||||
-rw-r--r-- | src/core/hle/service/time/time.cpp | 58 | ||||
-rw-r--r-- | src/core/hle/service/time/time.h | 28 | ||||
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 10 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 17 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 24 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 21 | ||||
-rw-r--r-- | src/video_core/textures/decoders.cpp | 9 |
14 files changed, 226 insertions, 40 deletions
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index c9257de77..eaa5395ac 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -29,7 +29,10 @@ enum class ControlCommand : u32 { }; enum class CommandType : u32 { + Invalid = 0, + LegacyRequest = 1, Close = 2, + LegacyControl = 3, Request = 4, Control = 5, RequestWithContext = 6, diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index 5be20c878..e1b5430bf 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h @@ -21,7 +21,9 @@ enum { // Confirmed Switch OS error codes MisalignedAddress = 102, + InvalidProcessorId = 113, InvalidHandle = 114, + InvalidCombination = 116, Timeout = 117, SynchronizationCanceled = 118, TooLarge = 119, diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 0811a16b8..ec3601e8b 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -732,7 +732,7 @@ static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) } static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) { - NGLOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:08X}, core=0x{:X}", thread_handle, + NGLOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle, mask, core); const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); @@ -740,6 +740,31 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) { return ERR_INVALID_HANDLE; } + if (core == THREADPROCESSORID_DEFAULT) { + ASSERT(thread->owner_process->ideal_processor != THREADPROCESSORID_DEFAULT); + // Set the target CPU to the one specified in the process' exheader. + core = thread->owner_process->ideal_processor; + mask = 1 << core; + } + + if (mask == 0) { + return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination); + } + + /// This value is used to only change the affinity mask without changing the current ideal core. + static constexpr u32 OnlyChangeMask = static_cast<u32>(-3); + + if (core == OnlyChangeMask) { + core = thread->ideal_core; + } else if (core >= Core::NUM_CPU_CORES && core != -1) { + return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidProcessorId); + } + + // Error out if the input core isn't enabled in the input mask. + if (core < Core::NUM_CPU_CORES && (mask & (1 << core)) == 0) { + return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination); + } + thread->ChangeCore(core, mask); return RESULT_SUCCESS; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 46fcdefb8..cffa7ca83 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -133,8 +133,11 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { auto lock_owner = thread->lock_owner; // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance - // and don't have a lock owner. - ASSERT(lock_owner == nullptr); + // and don't have a lock owner unless SignalProcessWideKey was called first and the thread + // wasn't awakened due to the mutex already being acquired. + if (lock_owner) { + lock_owner->RemoveMutexWaiter(thread); + } } if (resume) @@ -460,13 +463,13 @@ void Thread::UpdatePriority() { void Thread::ChangeCore(u32 core, u64 mask) { ideal_core = core; - mask = mask; + affinity_mask = mask; if (status != THREADSTATUS_READY) { return; } - boost::optional<s32> new_processor_id{GetNextProcessorId(mask)}; + boost::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)}; if (!new_processor_id) { new_processor_id = processor_id; @@ -476,7 +479,7 @@ void Thread::ChangeCore(u32 core, u64 mask) { new_processor_id = ideal_core; } - ASSERT(new_processor_id < 4); + ASSERT(*new_processor_id < 4); // Add thread to new core's scheduler auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id); diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 1891255cb..00c5308ba 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -329,6 +329,7 @@ public: {130, nullptr, "SwapNpadAssignment"}, {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, + {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, {201, &Hid::SendVibrationValue, "SendVibrationValue"}, {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"}, @@ -336,12 +337,41 @@ public: {204, nullptr, "PermitVibration"}, {205, nullptr, "IsVibrationPermitted"}, {206, &Hid::SendVibrationValues, "SendVibrationValues"}, + {207, nullptr, "SendVibrationGcErmCommand"}, + {208, nullptr, "GetActualVibrationGcErmCommand"}, + {209, nullptr, "BeginPermitVibrationSession"}, + {210, nullptr, "EndPermitVibrationSession"}, {300, nullptr, "ActivateConsoleSixAxisSensor"}, {301, nullptr, "StartConsoleSixAxisSensor"}, {302, nullptr, "StopConsoleSixAxisSensor"}, + {303, nullptr, "ActivateSevenSixAxisSensor"}, + {304, nullptr, "StartSevenSixAxisSensor"}, + {305, nullptr, "StopSevenSixAxisSensor"}, + {306, nullptr, "InitializeSevenSixAxisSensor"}, + {307, nullptr, "FinalizeSevenSixAxisSensor"}, + {308, nullptr, "SetSevenSixAxisSensorFusionStrength"}, + {309, nullptr, "GetSevenSixAxisSensorFusionStrength"}, {400, nullptr, "IsUsbFullKeyControllerEnabled"}, {401, nullptr, "EnableUsbFullKeyController"}, {402, nullptr, "IsUsbFullKeyControllerConnected"}, + {403, nullptr, "HasBattery"}, + {404, nullptr, "HasLeftRightBattery"}, + {405, nullptr, "GetNpadInterfaceType"}, + {406, nullptr, "GetNpadLeftRightInterfaceType"}, + {500, nullptr, "GetPalmaConnectionHandle"}, + {501, nullptr, "InitializePalma"}, + {502, nullptr, "AcquirePalmaOperationCompleteEvent"}, + {503, nullptr, "GetPalmaOperationInfo"}, + {504, nullptr, "PlayPalmaActivity"}, + {505, nullptr, "SetPalmaFrModeType"}, + {506, nullptr, "ReadPalmaStep"}, + {507, nullptr, "EnablePalmaStep"}, + {508, nullptr, "SuspendPalmaStep"}, + {509, nullptr, "ResetPalmaStep"}, + {510, nullptr, "ReadPalmaApplicationSection"}, + {511, nullptr, "WritePalmaApplicationSection"}, + {512, nullptr, "ReadPalmaUniqueCode"}, + {513, nullptr, "SetPalmaUniqueCodeInvalid"}, {1000, nullptr, "SetNpadCommunicationMode"}, {1001, nullptr, "GetNpadCommunicationMode"}, }; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index e979b9707..7872d1e09 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -16,7 +16,11 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector< case IoctlCommand::IocGetConfigCommand: return NvOsGetConfigU32(input, output); case IoctlCommand::IocCtrlEventWaitCommand: - return IocCtrlEventWait(input, output); + return IocCtrlEventWait(input, output, false); + case IoctlCommand::IocCtrlEventWaitAsyncCommand: + return IocCtrlEventWait(input, output, true); + case IoctlCommand::IocCtrlEventRegisterCommand: + return IocCtrlEventRegister(input, output); } UNIMPLEMENTED_MSG("Unimplemented ioctl"); return 0; @@ -45,11 +49,13 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& return 0; } -u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) { +u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, + bool is_async) { IocCtrlEventWaitParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); - NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id={} threshold={} timeout={}", - params.syncpt_id, params.threshold, params.timeout); + NGLOG_WARNING(Service_NVDRV, + "(STUBBED) called, syncpt_id={}, threshold={}, timeout={}, is_async={}", + params.syncpt_id, params.threshold, params.timeout, is_async); // TODO(Subv): Implement actual syncpt waiting. params.value = 0; @@ -57,4 +63,10 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& return 0; } +u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { + NGLOG_WARNING(Service_NVDRV, "(STUBBED) called"); + // TODO(bunnei): Implement this. + return 0; +} + } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index aa9b5a14b..090261a60 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -134,7 +134,9 @@ private: u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); - u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output); + u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async); + + u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 2eb37fb42..654012189 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include <chrono> +#include <ctime> #include "common/logging/log.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" @@ -77,7 +78,7 @@ public: {3, nullptr, "LoadLocationNameList"}, {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, {5, nullptr, "GetTimeZoneRuleVersion"}, - {100, nullptr, "ToCalendarTime"}, + {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, {200, nullptr, "ToPosixTime"}, {201, nullptr, "ToPosixTimeWithMyRule"}, @@ -86,9 +87,11 @@ public: } private: + LocationName location_name{"UTC"}; + TimeZoneRule my_time_zone_rule{}; + void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { - NGLOG_WARNING(Service_Time, "(STUBBED) called"); - LocationName location_name{}; + NGLOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2}; rb.Push(RESULT_SUCCESS); rb.PushRaw(location_name); @@ -103,23 +106,70 @@ private: void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { NGLOG_WARNING(Service_Time, "(STUBBED) called"); + + ctx.WriteBuffer(&my_time_zone_rule, sizeof(TimeZoneRule)); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + void ToCalendarTime(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 posix_time = rp.Pop<u64>(); + + NGLOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time); + + TimeZoneRule time_zone_rule{}; + auto buffer = ctx.ReadBuffer(); + std::memcpy(&time_zone_rule, buffer.data(), buffer.size()); + + CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; + CalendarAdditionalInfo additional_info{}; + + PosixToCalendar(posix_time, calendar_time, additional_info, time_zone_rule); + + IPC::ResponseBuilder rb{ctx, 10}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(calendar_time); + rb.PushRaw(additional_info); + } + void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - u64 posix_time = rp.Pop<u64>(); + const u64 posix_time = rp.Pop<u64>(); NGLOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time); CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; CalendarAdditionalInfo additional_info{}; + + PosixToCalendar(posix_time, calendar_time, additional_info, my_time_zone_rule); + IPC::ResponseBuilder rb{ctx, 10}; rb.Push(RESULT_SUCCESS); rb.PushRaw(calendar_time); rb.PushRaw(additional_info); } + + void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, + CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { + std::time_t t(posix_time); + std::tm* tm = std::localtime(&t); + if (!tm) { + return; + } + calendar_time.year = tm->tm_year + 1900; + calendar_time.month = tm->tm_mon + 1; + calendar_time.day = tm->tm_mday; + calendar_time.hour = tm->tm_hour; + calendar_time.minute = tm->tm_min; + calendar_time.second = tm->tm_sec; + + additional_info.day_of_week = tm->tm_wday; + additional_info.day_of_year = tm->tm_yday; + std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC")); + additional_info.utc_offset = 0; + } }; void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 12fe1995a..49af38589 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -4,13 +4,13 @@ #pragma once +#include <array> #include "core/hle/service/service.h" namespace Service::Time { -// TODO(Rozelette) RE this structure struct LocationName { - INSERT_PADDING_BYTES(0x24); + std::array<u8, 0x24> name; }; static_assert(sizeof(LocationName) == 0x24, "LocationName is incorrect size"); @@ -25,26 +25,34 @@ struct CalendarTime { }; static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size"); -// TODO(Rozelette) RE this structure struct CalendarAdditionalInfo { - INSERT_PADDING_BYTES(0x18); + u32_le day_of_week; + u32_le day_of_year; + std::array<u8, 8> name; + INSERT_PADDING_BYTES(1); + s32_le utc_offset; }; static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo structure has incorrect size"); -// TODO(bunnei) RE this structure -struct SystemClockContext { - INSERT_PADDING_BYTES(0x20); +// TODO(mailwl) RE this structure +struct TimeZoneRule { + INSERT_PADDING_BYTES(0x4000); }; -static_assert(sizeof(SystemClockContext) == 0x20, - "SystemClockContext structure has incorrect size"); struct SteadyClockTimePoint { - u64 value; + u64_le value; INSERT_PADDING_WORDS(4); }; static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size"); +struct SystemClockContext { + u64_le offset; + SteadyClockTimePoint time_point; +}; +static_assert(sizeof(SystemClockContext) == 0x20, + "SystemClockContext structure has incorrect size"); + class Module final { public: class Interface : public ServiceFramework<Interface> { diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index d75de85e2..f32a17057 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -75,6 +75,10 @@ union Attribute { enum class Index : u64 { Position = 7, Attribute_0 = 8, + // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex + // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval + // shader. + TessCoordInstanceIDVertexID = 47, }; union { @@ -456,9 +460,9 @@ private: INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), INST("0101110010010---", Id::RRO, Type::Arithmetic, "RRO"), - INST("0100110010101---", Id::F2F_C, Type::Arithmetic, "F2F_C"), - INST("0101110010101---", Id::F2F_R, Type::Arithmetic, "F2F_R"), - INST("0011100-10101---", Id::F2F_IMM, Type::Arithmetic, "F2F_IMM"), + INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), + INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), + INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 5bb34037b..65d643447 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -45,21 +45,23 @@ struct FormatTuple { static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8 - {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false}, // B5G6R5 + {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false}, // B5G6R5 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false}, // A2B10G10R10 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false}, // A1B5G5R5 {GL_R8, GL_RED, GL_UNSIGNED_BYTE, false}, // R8 + {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false}, // RGBA16F {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45 + {GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_INT_8_8_8_8, true}, // DXN1 }}; static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); if (type == SurfaceType::ColorTexture) { ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size()); - // For now only UNORM components are supported - ASSERT(component_type == ComponentType::UNorm); + // For now only UNORM components are supported, or RGBA16F which is type FLOAT + ASSERT(component_type == ComponentType::UNorm || pixel_format == PixelFormat::RGBA16F); return tex_format_tuples[static_cast<unsigned int>(pixel_format)]; } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { // TODO(Subv): Implement depth formats @@ -110,8 +112,9 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra: morton_to_gl_fns = { MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>, MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::A1B5G5R5>, - MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::DXT1>, - MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>, + MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::RGBA16F>, + MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, + MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, }; static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr, @@ -123,7 +126,9 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra: MortonCopy<false, PixelFormat::A2B10G10R10>, MortonCopy<false, PixelFormat::A1B5G5R5>, MortonCopy<false, PixelFormat::R8>, - // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported + MortonCopy<false, PixelFormat::RGBA16F>, + // TODO(Subv): Swizzling the DXT1/DXT23/DXT45/DXN1 formats is not yet supported + nullptr, nullptr, nullptr, nullptr, diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index fc09f108c..6f08678ab 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -59,9 +59,11 @@ struct SurfaceParams { A2B10G10R10 = 2, A1B5G5R5 = 3, R8 = 4, - DXT1 = 5, - DXT23 = 6, - DXT45 = 7, + RGBA16F = 5, + DXT1 = 6, + DXT23 = 7, + DXT45 = 8, + DXN1 = 9, // This is also known as BC4 Max, Invalid = 255, @@ -102,9 +104,11 @@ struct SurfaceParams { 1, // A2B10G10R10 1, // A1B5G5R5 1, // R8 + 2, // RGBA16F 4, // DXT1 4, // DXT23 4, // DXT45 + 4, // DXN1 }}; ASSERT(static_cast<size_t>(format) < compression_factor_table.size()); @@ -124,9 +128,11 @@ struct SurfaceParams { 32, // A2B10G10R10 16, // A1B5G5R5 8, // R8 + 64, // RGBA16F 64, // DXT1 128, // DXT23 128, // DXT45 + 64, // DXN1 }}; ASSERT(static_cast<size_t>(format) < bpp_table.size()); @@ -143,6 +149,8 @@ struct SurfaceParams { return PixelFormat::ABGR8; case Tegra::RenderTargetFormat::RGB10_A2_UNORM: return PixelFormat::A2B10G10R10; + case Tegra::RenderTargetFormat::RGBA16_FLOAT: + return PixelFormat::RGBA16F; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); @@ -172,12 +180,16 @@ struct SurfaceParams { return PixelFormat::A1B5G5R5; case Tegra::Texture::TextureFormat::R8: return PixelFormat::R8; + case Tegra::Texture::TextureFormat::R16_G16_B16_A16: + return PixelFormat::RGBA16F; case Tegra::Texture::TextureFormat::DXT1: return PixelFormat::DXT1; case Tegra::Texture::TextureFormat::DXT23: return PixelFormat::DXT23; case Tegra::Texture::TextureFormat::DXT45: return PixelFormat::DXT45; + case Tegra::Texture::TextureFormat::DXN1: + return PixelFormat::DXN1; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); @@ -197,12 +209,16 @@ struct SurfaceParams { return Tegra::Texture::TextureFormat::A1B5G5R5; case PixelFormat::R8: return Tegra::Texture::TextureFormat::R8; + case PixelFormat::RGBA16F: + return Tegra::Texture::TextureFormat::R16_G16_B16_A16; case PixelFormat::DXT1: return Tegra::Texture::TextureFormat::DXT1; case PixelFormat::DXT23: return Tegra::Texture::TextureFormat::DXT23; case PixelFormat::DXT45: return Tegra::Texture::TextureFormat::DXT45; + case PixelFormat::DXN1: + return Tegra::Texture::TextureFormat::DXN1; default: UNREACHABLE(); } @@ -226,6 +242,8 @@ struct SurfaceParams { case Tegra::RenderTargetFormat::RGBA8_SRGB: case Tegra::RenderTargetFormat::RGB10_A2_UNORM: return ComponentType::UNorm; + case Tegra::RenderTargetFormat::RGBA16_FLOAT: + return ComponentType::Float; default: NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); UNREACHABLE(); diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 75822e750..68efe74b8 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -299,7 +299,7 @@ public: * are stored as floats, so this may require conversion. * @param reg The destination register to use. * @param elem The element to use for the operation. - * @param attribute The input attibute to use as the source value. + * @param attribute The input attribute to use as the source value. */ void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { std::string dest = GetRegisterAsFloat(reg); @@ -451,6 +451,12 @@ private: switch (attribute) { case Attribute::Index::Position: return "position"; + case Attribute::Index::TessCoordInstanceIDVertexID: + // TODO(Subv): Find out what the values are for the first two elements when inside a + // vertex shader, and what's the value of the fourth element when inside a Tess Eval + // shader. + ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex); + return "vec4(0, 0, gl_InstanceID, gl_VertexID)"; default: const u32 index{static_cast<u32>(attribute) - static_cast<u32>(Attribute::Index::Attribute_0)}; @@ -834,13 +840,14 @@ private: } case OpCode::Type::Conversion: { ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); - ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); switch (opcode->GetId()) { case OpCode::Id::I2I_R: case OpCode::Id::I2F_R: { + ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); + std::string op_a = regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); @@ -851,6 +858,16 @@ private: regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); break; } + case OpCode::Id::F2F_R: { + std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); + + if (instr.conversion.abs_a) { + op_a = "abs(" + op_a + ')'; + } + + regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); + break; + } default: { NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); UNREACHABLE(); diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 9d7b73b73..2d2af5554 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -46,6 +46,7 @@ void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_ u32 BytesPerPixel(TextureFormat format) { switch (format) { case TextureFormat::DXT1: + case TextureFormat::DXN1: // In this case a 'pixel' actually refers to a 4x4 tile. return 8; case TextureFormat::DXT23: @@ -60,6 +61,8 @@ u32 BytesPerPixel(TextureFormat format) { return 2; case TextureFormat::R8: return 1; + case TextureFormat::R16_G16_B16_A16: + return 8; default: UNIMPLEMENTED_MSG("Format not implemented"); break; @@ -77,7 +80,9 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, case TextureFormat::DXT1: case TextureFormat::DXT23: case TextureFormat::DXT45: - // In the DXT formats, each 4x4 tile is swizzled instead of just individual pixel values. + case TextureFormat::DXN1: + // In the DXT and DXN formats, each 4x4 tile is swizzled instead of just individual pixel + // values. CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, unswizzled_data.data(), true, block_height); break; @@ -86,6 +91,7 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, case TextureFormat::A1B5G5R5: case TextureFormat::B5G6R5: case TextureFormat::R8: + case TextureFormat::R16_G16_B16_A16: CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, unswizzled_data.data(), true, block_height); break; @@ -106,6 +112,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat case TextureFormat::DXT1: case TextureFormat::DXT23: case TextureFormat::DXT45: + case TextureFormat::DXN1: case TextureFormat::A8R8G8B8: case TextureFormat::A2B10G10R10: case TextureFormat::A1B5G5R5: |