diff options
-rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 7 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | 32 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | 38 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.cpp | 2 | ||||
-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 | 6 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 7 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 17 | ||||
-rw-r--r-- | src/video_core/textures/decoders.cpp | 6 |
12 files changed, 185 insertions, 28 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7ab60c5bc..aff1d2180 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -175,6 +175,8 @@ add_library(core STATIC hle/service/nvdrv/devices/nvhost_ctrl_gpu.h hle/service/nvdrv/devices/nvhost_gpu.cpp hle/service/nvdrv/devices/nvhost_gpu.h + hle/service/nvdrv/devices/nvhost_nvdec.cpp + hle/service/nvdrv/devices/nvhost_nvdec.h hle/service/nvdrv/devices/nvmap.cpp hle/service/nvdrv/devices/nvmap.h hle/service/nvdrv/interface.cpp diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0075e4a0f..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) diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp new file mode 100644 index 000000000..0b6c22898 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -0,0 +1,32 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" + +namespace Service::Nvidia::Devices { + +u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { + NGLOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", + command.raw, input.size(), output.size()); + + switch (static_cast<IoctlCommand>(command.raw)) { + case IoctlCommand::IocSetNVMAPfdCommand: + return SetNVMAPfd(input, output); + } + + UNIMPLEMENTED_MSG("Unimplemented ioctl"); + return 0; +} + +u32 nvhost_nvdec::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { + IoctlSetNvmapFD params{}; + std::memcpy(¶ms, input.data(), input.size()); + NGLOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); + nvmap_fd = params.nvmap_fd; + return 0; +} + +} // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h new file mode 100644 index 000000000..0192aecdd --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -0,0 +1,38 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <cstdlib> +#include <cstring> +#include <vector> +#include "common/common_types.h" +#include "core/hle/service/nvdrv/devices/nvdevice.h" + +namespace Service::Nvidia::Devices { + +class nvhost_nvdec final : public nvdevice { +public: + nvhost_nvdec() = default; + ~nvhost_nvdec() override = default; + + u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; + +private: + enum class IoctlCommand : u32_le { + IocSetNVMAPfdCommand = 0x40044801, + }; + + struct IoctlSetNvmapFD { + u32_le nvmap_fd; + }; + static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); + + u32_le nvmap_fd{}; + + u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); +}; + +} // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index a6a4ab7d3..cc5cfe34e 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -9,6 +9,7 @@ #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" +#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" #include "core/hle/service/nvdrv/devices/nvmap.h" #include "core/hle/service/nvdrv/interface.h" #include "core/hle/service/nvdrv/nvdrv.h" @@ -36,6 +37,7 @@ Module::Module() { devices["/dev/nvmap"] = nvmap_dev; devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>(); + devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>(); } u32 Module::Open(std::string device_name) { 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 4ed918a76..fd4e0746e 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -311,8 +311,10 @@ public: FMUL_R, FMUL_IMM, FMUL32_IMM, - MUFU, // Multi-Function Operator - RRO, // Range Reduction Operator + MUFU, // Multi-Function Operator + RRO_C, // Range Reduction Operator + RRO_R, + RRO_IMM, F2F_C, F2F_R, F2F_IMM, @@ -474,7 +476,9 @@ private: INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), - INST("0101110010010---", Id::RRO, Type::Arithmetic, "RRO"), + INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), + INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), + INST("0011100-10010---", Id::RRO_IMM, Type::Arithmetic, "RRO_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"), diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 10a460a82..65d643447 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -53,6 +53,7 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form {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) { @@ -113,7 +114,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra: MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::A1B5G5R5>, MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::RGBA16F>, MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>, - MortonCopy<true, PixelFormat::DXT45>, + MortonCopy<true, PixelFormat::DXT45>, MortonCopy<true, PixelFormat::DXN1>, }; static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr, @@ -126,7 +127,8 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra: MortonCopy<false, PixelFormat::A1B5G5R5>, MortonCopy<false, PixelFormat::R8>, MortonCopy<false, PixelFormat::RGBA16F>, - // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported + // 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 07461017d..6f08678ab 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -63,6 +63,7 @@ struct SurfaceParams { DXT1 = 6, DXT23 = 7, DXT45 = 8, + DXN1 = 9, // This is also known as BC4 Max, Invalid = 255, @@ -107,6 +108,7 @@ struct SurfaceParams { 4, // DXT1 4, // DXT23 4, // DXT45 + 4, // DXN1 }}; ASSERT(static_cast<size_t>(format) < compression_factor_table.size()); @@ -130,6 +132,7 @@ struct SurfaceParams { 64, // DXT1 128, // DXT23 128, // DXT45 + 64, // DXN1 }}; ASSERT(static_cast<size_t>(format) < bpp_table.size()); @@ -185,6 +188,8 @@ struct SurfaceParams { 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(); @@ -212,6 +217,8 @@ struct SurfaceParams { return Tegra::Texture::TextureFormat::DXT23; case PixelFormat::DXT45: return Tegra::Texture::TextureFormat::DXT45; + case PixelFormat::DXN1: + return Tegra::Texture::TextureFormat::DXN1; default: UNREACHABLE(); } diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 88502a8a7..86d880dfc 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -792,8 +792,13 @@ private: 1, 1); break; } - case OpCode::Id::RRO: { - NGLOG_DEBUG(HW_GPU, "Skipping RRO instruction"); + case OpCode::Id::RRO_C: + case OpCode::Id::RRO_R: + case OpCode::Id::RRO_IMM: { + // Currently RRO is only implemented as a register move. + // Usage of `abs_b` and `negate_b` here should also be correct. + regs.SetRegisterToFloat(instr.gpr0, 0, op_b, 1, 1); + NGLOG_WARNING(HW_GPU, "RRO instruction is incomplete"); break; } default: { @@ -923,8 +928,8 @@ private: const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); const std::string sampler = GetSampler(instr.sampler); const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; - // Add an extra scope and declare the texture coords inside to prevent overwriting - // them in case they are used as outputs of the texs instruction. + // Add an extra scope and declare the texture coords inside to prevent + // overwriting them in case they are used as outputs of the texs instruction. shader.AddLine("{"); ++shader.scope; shader.AddLine(coord); @@ -1002,8 +1007,8 @@ private: '(' + 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 + // Set the secondary predicate to the result of !Predicate OP SecondPredicate, + // if enabled SetPredicate(instr.fsetp.pred0, "!(" + predicate + ") " + combiner + " (" + second_pred + ')'); } diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 0179663e8..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: @@ -79,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; @@ -109,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: |